Issues (244)

Security Analysis    not enabled

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

  Cross-Site Scripting
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.
  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.
  File Manipulation
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.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  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.
  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.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
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.

src/N98/Magento/DbSettings.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * this file is part of magerun
4
 *
5
 * @author Tom Klingenberg <https://github.com/ktomk>
6
 */
7
8
namespace N98\Magento;
9
10
use ArrayAccess;
11
use ArrayIterator;
12
use BadMethodCallException;
13
use InvalidArgumentException;
14
use IteratorAggregate;
15
use PDO;
16
use PDOException;
17
use RuntimeException;
18
use SimpleXMLElement;
19
20
/**
21
 * Class DbSettings
22
 *
23
 * Database settings.
24
 *
25
 * The Magento database settings are stored in a SimpleXMLElement structure
26
 *
27
 * @package N98\Magento
28
 */
29
class DbSettings implements ArrayAccess, IteratorAggregate
30
{
31
    /**
32
     * @var string|null known field members
33
     */
34
    private $tablePrefix, $host, $port, $unixSocket, $dbName, $username, $password;
0 ignored issues
show
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
35
36
    /**
37
     * @var array field array
38
     */
39
    private $config;
40
41
    /**
42
     * @param string $file path to app/etc/local.xml
43
     */
44
    public function __construct($file)
45
    {
46
        $this->setFile($file);
47
    }
48
49
    /**
50
     * @param string $file path to app/etc/local.xml
51
     *
52
     * @throws InvalidArgumentException if the file is invalid
53
     */
54
    public function setFile($file)
55
    {
56
        if (!is_readable($file)) {
57
            throw new InvalidArgumentException(
58
                sprintf('"app/etc/local.xml"-file %s is not readable', var_export($file, true))
59
            );
60
        }
61
62
        $saved = libxml_use_internal_errors(true);
63
        $config = simplexml_load_file($file);
64
        libxml_use_internal_errors($saved);
65
66
        if (false === $config) {
67
            throw new InvalidArgumentException(
68
                sprintf('Unable to open "app/etc/local.xml"-file %s and parse it as XML', var_export($file, true))
69
            );
70
        }
71
72
        $resources = $config->global->resources;
73
        if (!$resources) {
74
            throw new InvalidArgumentException('DB global resources was not found in "app/etc/local.xml"-file');
75
        }
76
77
        if (!$resources->default_setup->connection) {
78
            throw new InvalidArgumentException('DB settings (default_setup) was not found in "app/etc/local.xml"-file');
79
        }
80
81
        $this->parseResources($resources);
82
    }
83
84
    /**
85
     * helper method to parse config file segment related to the database settings
86
     *
87
     * @param SimpleXMLElement $resources
88
     */
89
    private function parseResources(SimpleXMLElement $resources)
90
    {
91
        // default values
92
        $config = array(
93
            'host'        => null,
94
            'port'        => null,
95
            'unix_socket' => null,
96
            'dbname'      => null,
97
            'username'    => null,
98
            'password'    => null,
99
        );
100
101
        $config = array_merge($config, (array) $resources->default_setup->connection);
102
        $config['prefix'] = (string) $resources->db->table_prefix;
103
104
        // known parameters: host, port, unix_socket, dbname, username, password, options, charset, persistent,
105
        //                   driver_options
106
        //                   (port is deprecated; removed in magento 2, use port in host setting <host>:<port>)
107
108
        unset($config['comment']);
109
110
        /* @see Varien_Db_Adapter_Pdo_Mysql::_connect */
111
        if (strpos($config['host'], '/') !== false) {
112
            $config['unix_socket'] = (string) $config['host'];
113
            $config['host'] = null;
114
            $config['port'] = null;
115
        } elseif (strpos($config['host'], ':') !== false) {
116
            list($config['host'], $config['port']) = explode(':', $config['host']);
117
            $config['unix_socket'] = null;
118
        }
119
120
        $this->config = $config;
121
122
        $this->tablePrefix = $config['prefix'];
123
        $this->host = $config['host'];
124
        $this->port = $config['port'];
125
        $this->unixSocket = $config['unix_socket'];
126
        $this->dbName = $config['dbname'];
127
        $this->username = $config['username'];
128
        $this->password = $config['password'];
129
    }
130
131
    /**
132
     * Get Mysql PDO DSN
133
     *
134
     * @return string
135
     */
136
    public function getDsn()
137
    {
138
        $dsn = 'mysql:';
139
140
        $named = array();
141
142
        // blacklisted in prev. DSN creation: username, password, options, charset, persistent, driver_options, dbname
143
144
        if (isset($this->unixSocket)) {
145
            $named['unix_socket'] = $this->unixSocket;
146
        } else {
147
            $named['host'] = $this->host;
148
            if (isset($this->port)) {
149
                $named['port'] = $this->port;
150
            }
151
        }
152
153
        $options = array();
154
        foreach ($named as $name => $value) {
155
            $options[$name] = "{$name}={$value}";
156
        }
157
158
        return $dsn . implode(';', $options);
159
    }
160
161
    /**
162
     * Connects to the database without initializing magento
163
     *
164
     * @throws RuntimeException if pdo_mysql extension is not installed
165
     * @return PDO
166
     */
167
    public function getConnection()
168
    {
169
        if (!extension_loaded('pdo_mysql')) {
170
            throw new RuntimeException('pdo_mysql extension is not installed');
171
        }
172
173
        $database = $this->getDatabaseName();
174
175
        $connection = new PDO(
176
            $this->getDsn(),
177
            $this->getUsername(),
178
            $this->getPassword()
179
        );
180
181
        /** @link http://bugs.mysql.com/bug.php?id=18551 */
182
        $connection->query("SET SQL_MODE=''");
183
184
        try {
185
            $connection->query('USE ' . $this->quoteIdentifier($database));
186
        } catch (PDOException $e) {
187
            $message = sprintf("Unable to use database '%s': %s %s", $database, get_class($e), $e->getMessage());
188
            throw new RuntimeException($message, 0, $e);
189
        }
190
191
        $connection->query("SET NAMES utf8");
192
193
        $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
194
        $connection->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
195
196
        return $connection;
197
    }
198
199
    public function getMysqlClientToolConnectionString()
200
    {
201
        $segments = array();
202
203
        if (null !== $this->config['unix_socket']) {
204
            $segments[] = '--socket=' . escapeshellarg($this->config['unix_socket']);
205
        } else {
206
            $segments[] = '-h ' . escapeshellarg($this->config['host']);
207
        }
208
209
        $segments[] = '-u' . escapeshellarg($this->config['username']);
210
        if (null !== $this->config['port']) {
211
            $segments[] = '-P' . escapeshellarg($this->config['port']);
212
        }
213
        if (strlen($this->config['password'])) {
214
            $segments[] = '-p' . escapeshellarg($this->config['password']);
215
        }
216
        $segments[] = escapeshellarg($this->config['dbname']);
217
218
        return implode(' ', $segments);
219
    }
220
221
    /**
222
     * Mysql quoting of an identifier
223
     *
224
     * @param string $identifier UTF-8 encoded
225
     *
226
     * @return string quoted identifier
227
     */
228
    private function quoteIdentifier($identifier)
229
    {
230
        $quote = '`'; // le backtique
231
232
        $pattern = '~^(?:[\x1-\x7F]|[\xC2-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2})+$~';
233
234
        if (!preg_match($pattern, $identifier)) {
235
            throw new InvalidArgumentException(
236
                sprintf(
237
                    'Invalid identifier, must not contain NUL and must be UTF-8 encoded in the BMP: %s (hex: %s)',
238
                    var_export($identifier, true),
239
                    bin2hex($identifier)
240
                )
241
            );
242
        }
243
244
        return $quote . strtr($identifier, array($quote => $quote . $quote)) . $quote;
245
    }
246
247
    /**
248
     * @return bool
249
     */
250
    public function isSocketConnect()
251
    {
252
        return isset($this->config['unix_socket']);
253
    }
254
255
    /**
256
     * @return string table prefix, null if not in the settings (no or empty prefix)
257
     */
258
    public function getTablePrefix()
259
    {
260
        return $this->tablePrefix;
261
    }
262
263
    /**
264
     * @return string hostname, null if there is no hostname setup (e.g. unix_socket)
265
     */
266
    public function getHost()
267
    {
268
        return $this->host;
269
    }
270
271
    /**
272
     * @return string port, null if not setup
273
     */
274
    public function getPort()
275
    {
276
        return $this->port;
277
    }
278
279
    /**
280
     * @return string username
281
     */
282
    public function getUsername()
283
    {
284
        return $this->username;
285
    }
286
287
    /**
288
     * @return string password
289
     */
290
    public function getPassword()
291
    {
292
        return $this->password;
293
    }
294
295
    /**
296
     * @return string unix socket, null if not in use
297
     */
298
    public function getUnixSocket()
299
    {
300
        return $this->unixSocket;
301
    }
302
303
    /**
304
     * content of previous $dbSettings field of the DatabaseHelper
305
     *
306
     * @return array
307
     */
308
    public function getConfig()
309
    {
310
        return $this->config;
311
    }
312
313
    /**
314
     * @return string of the database identifier, null if not in use
315
     */
316
    public function getDatabaseName()
317
    {
318
        return $this->dbName;
319
    }
320
321
    /*
322
     * ArrayAccess interface
323
     */
324
325
    /**
326
     * @return boolean true on success or false on failure.
327
     */
328
    public function offsetExists($offset)
329
    {
330
        return isset($this->config[$offset]);
331
    }
332
333
    /**
334
     * @return mixed Can return all value types.
335
     */
336
    public function offsetGet($offset)
337
    {
338
        if (isset($this->config[$offset])) {
339
            return $this->config[$offset];
340
        }
341
342
        return;
343
    }
344
345
    /**
346
     * @param mixed $offset
347
     * @param mixed $value
348
     *
349
     * @throws BadMethodCallException
350
     */
351
    public function offsetSet($offset, $value)
352
    {
353
        throw new BadMethodCallException('dbSettings are read-only');
354
    }
355
356
    /**
357
     * @param mixed $offset
358
     *
359
     * @throws BadMethodCallException
360
     */
361
    public function offsetUnset($offset)
362
    {
363
        throw new BadMethodCallException('dbSettings are read-only');
364
    }
365
366
    /*
367
     * IteratorAggregate
368
     */
369
370
    /**
371
     * @return ArrayIterator
372
     */
373
    public function getIterator()
374
    {
375
        return new ArrayIterator($this->config);
376
    }
377
}
378