Issues (212)

Security Analysis    12 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting (2)
Response Splitting can be used to send arbitrary responses.
  File Manipulation (5)
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (1)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (2)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

core/common/Logging.php (7 issues)

1
<?php
2
3
/*
4
 * *****************************************************************************
5
 * Contributions to this work were made on behalf of the GÉANT project, a 
6
 * project that has received funding from the European Union’s Framework 
7
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
8
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
9
 * 691567 (GN4-1) and No. 731122 (GN4-2).
10
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
11
 * of the copyright in all material which was developed by a member of the GÉANT
12
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
13
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
14
 * UK as a branch of GÉANT Vereniging.
15
 * 
16
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
17
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
18
 *
19
 * License: see the web/copyright.inc.php file in the file structure or
20
 *          <base_url>/copyright.php after deploying the software
21
 */
22
23
namespace core\common;
24
25
use \Exception;
0 ignored issues
show
The type \Exception was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
27
class Logging
28
{
29
30
    /**
31
     * We don't have a lot to do here, but at least make sure that the logdir 
32
     * is specified and exists.
33
     * 
34
     * @throws Exception
35
     */
36
    public function __construct()
37
    {
38
        if (!isset(\config\Master::PATHS['logdir'])) {
39
            throw new Exception("No logdir was specified in the configuration. We cannot continue without one!");
40
        }
41
    }
42
43
    /**
44
     * writes a message to file
45
     * 
46
     * @param string $filename the name of the log file, relative (path to logdir gets prepended)
47
     * @param string $message  what to write into the file
48
     * @return void
49
     */
50
    private function writeToFile($filename, $message)
51
    {
52
        file_put_contents(\config\Master::PATHS['logdir'] . "/$filename", sprintf("%-015s", microtime(TRUE)) . $message, FILE_APPEND);
0 ignored issues
show
Security File Manipulation introduced by
config\Master::PATHS['logdir'] . '/'.$filename can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_REQUEST
    in web/lib/user/Gui.php on line 41

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
Security File Manipulation introduced by
sprintf('%-015s', microtime(TRUE)) . $message can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read tainted data from array, and Data is passed through strip_tags(), and Data is passed through htmlspecialchars(), and htmlspecialchars(strip_tags($_SERVER['HTTP_USER_AGENT']), core\ENT_QUOTES) is assigned to $browser in core/UserAPI.php on line 525
  1. Read tainted data from array, and Data is passed through strip_tags(), and Data is passed through htmlspecialchars(), and htmlspecialchars(strip_tags($_SERVER['HTTP_USER_AGENT']), core\ENT_QUOTES) is assigned to $browser
    in core/UserAPI.php on line 525
  2. Logging::debug() is called
    in core/UserAPI.php on line 532
  3. Enters via parameter $stuff
    in core/common/Logging.php on line 76
  4. $prefix . $stuff . $suffix is assigned to $output
    in core/common/Logging.php on line 92
  5. Logging::writeToFile() is called
    in core/common/Logging.php on line 96
  6. Enters via parameter $message
    in core/common/Logging.php on line 50
  2. Path: Read from $_GET, and Data is passed through strip_tags(), and Data is passed through htmlspecialchars(), and htmlspecialchars(strip_tags($_GET['device'])) is assigned to $devId in core/UserAPI.php on line 571
  1. Read from $_GET, and Data is passed through strip_tags(), and Data is passed through htmlspecialchars(), and htmlspecialchars(strip_tags($_GET['device'])) is assigned to $devId
    in core/UserAPI.php on line 571
  2. $devId is returned
    in core/UserAPI.php on line 583
  3. $this->deviceFromRequest() is assigned to $devId
    in core/UserAPI.php on line 517
  4. Data is passed through returnDevice(), and $this->returnDevice($devId, $Dev[$devId]) is assigned to $ret
    in core/UserAPI.php on line 519
  5. $ret is returned
    in core/UserAPI.php on line 521
  6. $this->detectOS() is assigned to property Gui::$operatingSystem
    in web/lib/user/Gui.php on line 48
  7. Read from property Gui::$operatingSystem, and Logging::debug() is called
    in web/lib/user/Gui.php on line 49
  8. Enters via parameter $stuff
    in core/common/Logging.php on line 76
  9. $prefix . $stuff . $suffix is assigned to $output
    in core/common/Logging.php on line 92
  10. Logging::writeToFile() is called
    in core/common/Logging.php on line 96
  11. Enters via parameter $message
    in core/common/Logging.php on line 50
  3. Path: Read from $_POST, and Data is passed through strip_tags(), and Data is passed through htmlspecialchars(), and htmlspecialchars(strip_tags($_POST['device'])) is assigned to $devId in core/UserAPI.php on line 573
  1. Read from $_POST, and Data is passed through strip_tags(), and Data is passed through htmlspecialchars(), and htmlspecialchars(strip_tags($_POST['device'])) is assigned to $devId
    in core/UserAPI.php on line 573
  2. $devId is returned
    in core/UserAPI.php on line 583
  3. $this->deviceFromRequest() is assigned to $devId
    in core/UserAPI.php on line 517
  4. Data is passed through returnDevice(), and $this->returnDevice($devId, $Dev[$devId]) is assigned to $ret
    in core/UserAPI.php on line 519
  5. $ret is returned
    in core/UserAPI.php on line 521
  6. $this->detectOS() is assigned to property Gui::$operatingSystem
    in web/lib/user/Gui.php on line 48
  7. Read from property Gui::$operatingSystem, and Logging::debug() is called
    in web/lib/user/Gui.php on line 49
  8. Enters via parameter $stuff
    in core/common/Logging.php on line 76
  9. $prefix . $stuff . $suffix is assigned to $output
    in core/common/Logging.php on line 92
  10. Logging::writeToFile() is called
    in core/common/Logging.php on line 96
  11. Enters via parameter $message
    in core/common/Logging.php on line 50

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
53
    }
54
55
    /**
56
     * writes a message to file (static version)
57
     * 
58
     * @param string $filename the name of the log file, relative (path to logdir gets prepended)
59
     * @param string $message  what to write into the file
60
     * @return void
61
     */
62
    private static function writeToFile_s($filename, $message)
0 ignored issues
show
Method name "Logging::writeToFile_s" is not in camel caps format
Loading history...
63
    {
64
        file_put_contents(\config\Master::PATHS['logdir'] . "/$filename", sprintf("%-015s", microtime(TRUE)) . $message, FILE_APPEND);
65
    }
66
    
67
    /**
68
     * write debug messages to the log, if the debug level is high enough
69
     *
70
     * @param int    $level  the debug level of the message that is to be logged
71
     * @param mixed  $stuff  the stuff to be logged (via print_r)
72
     * @param string $prefix prefix to the message, optional
73
     * @param string $suffix suffix to the message, optional
74
     * @return void
75
     */
76
    public function debug($level, $stuff, $prefix = '', $suffix = '')
77
    {
78
        if (\config\Master::DEBUG_LEVEL < $level) {
79
            return;
80
        }
81
82
        $output = " ($level) ";
83
        if ($level > 3) {
84
            $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
85
            $orig_file = $backtrace[1]['file'] ?? "no file";
86
            $file = str_replace(ROOT, "", $orig_file);
87
            $function = $backtrace[1]['function'] ?? "no function";
88
            $line = $backtrace[1]['line'] ?? "no line";
89
            $output .= " [$file / $function / $line] ";
90
        }
91
        if (is_string($stuff)) {
92
            $output .= $prefix . $stuff . $suffix;
93
        } else {
94
            $output .= $prefix . var_export($stuff, TRUE) . $suffix;
95
        }
96
        $this->writeToFile("debug.log", $output);
97
98
        return;
99
    }
100
    
101
    /**
102
     * write debug messages to the log, if the debug level is high enough - static version
103
     *
104
     * @param int    $level  the debug level of the message that is to be logged
105
     * @param mixed  $stuff  the stuff to be logged (via print_r)
106
     * @param string $prefix prefix to the message, optional
107
     * @param string $suffix suffix to the message, optional
108
     * @return void
109
     */    
110
    public static function debug_s($level, $stuff, $prefix = '', $suffix = '')
0 ignored issues
show
Method name "Logging::debug_s" is not in camel caps format
Loading history...
111
    {
112
        if (\config\Master::DEBUG_LEVEL < $level) {
113
            return;
114
        }
115
116
        $output = " ($level) ";
117
        if ($level > 3) {
118
            $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
119
            $orig_file = $backtrace[1]['file'] ?? "no file";
120
            $file = str_replace(ROOT, "", $orig_file);
121
            $function = $backtrace[1]['function'] ?? "no function";
122
            $line = $backtrace[1]['line'] ?? "no line";
123
            $output .= " [$file / $function / $line] ";
124
        }
125
        if (is_string($stuff)) {
126
            $output .= $prefix . $stuff . $suffix;
127
        } else {
128
            $output .= $prefix . var_export($stuff, TRUE) . $suffix;
129
        }
130
        self::writeToFile_s("debug.log", $output);
131
        return;
132
    }   
133
134
    /**
135
     * Writes an audit log entry to the audit log file. These audits are semantic logs; they don't record every single modification
136
     * in the database, but provide a logical "who did what" overview. The exact modification SQL statements are logged
137
     * automatically with writeSQLAudit() instead. The log file path is configurable in _config.php.
138
     * 
139
     * @param string $user     persistent identifier of the user who triggered the action
140
     * @param string $category type of modification, from the fixed vocabulary: "NEW", "OWN", "MOD", "DEL"
141
     * @param string $message  message to log into the audit log
142
     * @return boolean TRUE if successful. Will terminate script execution on failure. 
143
     * @throws Exception
144
     */
145
    public function writeAudit($user, $category, $message)
146
    {
147
        switch ($category) {
148
            case "NEW": // created a new object
149
            case "OWN": // ownership changes
150
            case "MOD": // modified existing object
151
            case "DEL": // deleted an object
152
                ob_start();
153
                echo " ($category)  $user : $message\n";
154
                $output = ob_get_clean();
155
                $this->writeToFile("audit-activity.log", $output);
156
                return TRUE;
157
            default:
158
                throw new Exception("Unable to write to AUDIT file (unknown category, requested data was $user, $category, $message!");
159
        }
160
    }
161
    
162
     /**
163
     * Writes an audit log entry to the audit log file - static version. These audits are semantic logs; they don't record every single modification
164
     * in the database, but provide a logical "who did what" overview. The exact modification SQL statements are logged
165
     * automatically with writeSQLAudit() instead. The log file path is configurable in _config.php.
166
     * 
167
     * @param string $user     persistent identifier of the user who triggered the action
168
     * @param string $category type of modification, from the fixed vocabulary: "NEW", "OWN", "MOD", "DEL"
169
     * @param string $message  message to log into the audit log
170
     * @return boolean TRUE if successful. Will terminate script execution on failure. 
171
     * @throws Exception
172
     */
173
    public static function writeAudit_s($user, $category, $message)
0 ignored issues
show
Method name "Logging::writeAudit_s" is not in camel caps format
Loading history...
174
    {
175
        switch ($category) {
176
            case "NEW": // created a new object
177
            case "OWN": // ownership changes
178
            case "MOD": // modified existing object
179
            case "DEL": // deleted an object
180
                ob_start();
181
                echo " ($category)  $user : $message\n";
182
                $output = ob_get_clean();
183
                self::writeToFile_s("audit-activity.log", $output);
184
                return TRUE;
185
            default:
186
                throw new Exception("Unable to write to AUDIT file (unknown category, requested data was $user, $category, $message!");
187
        }
188
    }
189
190
    /**
191
     * Write an audit log entry to the SQL log file. Every SQL statement which is not a simple SELECT one will be written
192
     * to the log file. The log file path is configurable in _config.php.
193
     * 
194
     * @param string $query the SQL query to be logged
195
     * @return void
196
     */
197
    public function writeSQLAudit($query)
198
    {
199
        // clean up text to be in one line, with no extra spaces
200
        // also clean up non UTF-8 to sanitise possibly malicious inputs
201
        $logTextStep1 = preg_replace("/[\n\r]/", "", $query);
202
        $logTextStep2 = preg_replace("/ +/", " ", $logTextStep1);
203
        $logTextStep3 = iconv("UTF-8", "UTF-8//IGNORE", $logTextStep2);
204
        $this->writeToFile("audit-SQL.log", " " . $logTextStep3 . "\n");
205
    }
206
    
207
    
208
    /**
209
     * Write an audit log entry to the SQL log file. Every SQL statement which is not a simple SELECT one will be written
210
     * to the log file. The log file path is configurable in _config.php.
211
     * 
212
     * @param string $query the SQL query to be logged
213
     * @return void
214
     */
215
    public static function writeSQLAudit_s($query)
0 ignored issues
show
Method name "Logging::writeSQLAudit_s" is not in camel caps format
Loading history...
216
    {
217
        // clean up text to be in one line, with no extra spaces
218
        // also clean up non UTF-8 to sanitise possibly malicious inputs
219
        $logTextStep1 = preg_replace("/[\n\r]/", "", $query);
220
        $logTextStep2 = preg_replace("/ +/", " ", $logTextStep1);
221
        $logTextStep3 = iconv("UTF-8", "UTF-8//IGNORE", $logTextStep2);
222
        self::writeToFile_s("audit-SQL.log", " " . $logTextStep3 . "\n");
223
    }
224
}