Issues (501)

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.

classes/password.php (4 issues)

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
     * A Compatibility library with PHP 5.5's simplified password hashing API.
4
     *
5
     * @author Anthony Ferrara <[email protected]>
6
     * @license http://www.opensource.org/licenses/mit-license.html MIT License
7
     * @copyright 2012 The Authors
8
     */
9
10
if (!defined('PASSWORD_DEFAULT')) {
11
12
    define('PASSWORD_BCRYPT', 1);
13
    define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
14
15
    /**
16
     * Hash the password using the specified algorithm
17
     *
18
     * @param string $password The password to hash
19
     * @param int    $algo     The algorithm to use (Defined by PASSWORD_* constants)
20
     * @param array  $options  The options for the algorithm to use
21
     *
22
     * @return string|false The hashed password, or false on error.
23
     */
24
    function password_hash($password, $algo, array $options = array()) {
25
        if (!function_exists('crypt')) {
26
            trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
27
            return null;
28
        }
29
        if (!is_string($password)) {
30
            trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
31
            return null;
32
        }
33
        if (!is_int($algo)) {
34
            trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
35
            return null;
36
        }
37
        switch ($algo) {
38
            case PASSWORD_BCRYPT:
39
                // Note that this is a C constant, but not exposed to PHP, so we don't define it here.
40
                $cost = 10;
41
                if (isset($options['cost'])) {
42
                    $cost = $options['cost'];
43
                    if ($cost < 4 || $cost > 31) {
44
                        trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
45
                        return null;
46
                    }
47
                }
48
                // The length of salt to generate
49
                $raw_salt_len = 16;
50
                // The length required in the final serialization
51
                $required_salt_len = 22;
52
                $hash_format = sprintf("$2y$%02d$", $cost);
53
                break;
54
            default:
55
                trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
56
                return null;
57
        }
58
        if (isset($options['salt'])) {
59
            switch (gettype($options['salt'])) {
60
                case 'NULL':
61
                case 'boolean':
62
                case 'integer':
63
                case 'double':
64
                case 'string':
65
                    $salt = (string) $options['salt'];
66
                    break;
67
                case 'object':
0 ignored issues
show
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
68
                    if (method_exists($options['salt'], '__tostring')) {
69
                        $salt = (string) $options['salt'];
70
                        break;
71
                    }
72
                case 'array':
73
                case 'resource':
74
                default:
75
                    trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
76
                    return null;
77
            }
78
            if (strlen($salt) < $required_salt_len) {
79
                trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING);
80
                return null;
81
            } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
82
                $salt = str_replace('+', '.', base64_encode($salt));
83
            }
84
        } else {
85
            $buffer = '';
86
            $buffer_valid = false;
87
            if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
88
                $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
89
                if ($buffer) {
90
                    $buffer_valid = true;
91
                }
92
            }
93
            if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
94
                $buffer = openssl_random_pseudo_bytes($raw_salt_len);
95
                if ($buffer) {
96
                    $buffer_valid = true;
97
                }
98
            }
99
            if (!$buffer_valid && is_readable('/dev/urandom')) {
100
                $f = fopen('/dev/urandom', 'r');
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $f. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
101
                $read = strlen($buffer);
102
                while ($read < $raw_salt_len) {
103
                    $buffer .= fread($f, $raw_salt_len - $read);
104
                    $read = strlen($buffer);
105
                }
106
                fclose($f);
107
                if ($read >= $raw_salt_len) {
108
                    $buffer_valid = true;
109
                }
110
            }
111
            if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
112
                $bl = strlen($buffer);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $bl. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
113
                for ($i = 0; $i < $raw_salt_len; $i++) {
114
                    if ($i < $bl) {
115
                        $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
116
                    } else {
117
                        $buffer .= chr(mt_rand(0, 255));
118
                    }
119
                }
120
            }
121
            $salt = str_replace('+', '.', base64_encode($buffer));
122
        }
123
        $salt = substr($salt, 0, $required_salt_len);
124
125
        $hash = $hash_format . $salt;
126
127
        $ret = crypt($password, $hash);
128
129
        if (!is_string($ret) || strlen($ret) <= 13) {
130
            return false;
131
        }
132
133
        return $ret;
134
    }
135
136
    /**
137
     * Get information about the password hash. Returns an array of the information
138
     * that was used to generate the password hash.
139
     *
140
     * array(
141
     *    'algo' => 1,
142
     *    'algoName' => 'bcrypt',
143
     *    'options' => array(
144
     *        'cost' => 10,
145
     *    ),
146
     * )
147
     *
148
     * @param string $hash The password hash to extract info from
149
     *
150
     * @return array The array of information about the hash.
151
     */
152
    function password_get_info($hash) {
153
        $return = array(
154
            'algo' => 0,
155
            'algoName' => 'unknown',
156
            'options' => array(),
157
        );
158
        if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) {
159
            $return['algo'] = PASSWORD_BCRYPT;
160
            $return['algoName'] = 'bcrypt';
161
            list($cost) = sscanf($hash, "$2y$%d$");
162
            $return['options']['cost'] = $cost;
163
        }
164
        return $return;
165
    }
166
167
    /**
168
     * Determine if the password hash needs to be rehashed according to the options provided
169
     *
170
     * If the answer is true, after validating the password using password_verify, rehash it.
171
     *
172
     * @param string $hash    The hash to test
173
     * @param int    $algo    The algorithm used for new password hashes
174
     * @param array  $options The options array passed to password_hash
175
     *
176
     * @return boolean True if the password needs to be rehashed.
177
     */
178
    function password_needs_rehash($hash, $algo, array $options = array()) {
179
        $info = password_get_info($hash);
180
        if ($info['algo'] != $algo) {
181
            return true;
182
        }
183
        switch ($algo) {
184
            case PASSWORD_BCRYPT:
185
                $cost = isset($options['cost']) ? $options['cost'] : 10;
186
                if ($cost != $info['options']['cost']) {
187
                    return true;
188
                }
189
                break;
190
        }
191
        return false;
192
    }
193
194
    /**
195
     * Verify a password against a hash using a timing attack resistant approach
196
     *
197
     * @param string $password The password to verify
198
     * @param string $hash     The hash to verify against
199
     *
200
     * @return boolean If the password matches the hash
201
     */
202
    function password_verify($password, $hash) {
203
        if (!function_exists('crypt')) {
204
            trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
205
            return false;
206
        }
207
        $ret = crypt($password, $hash);
208
        if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
209
            return false;
210
        }
211
212
        $status = 0;
213
        for ($i = 0; $i < strlen($ret); $i++) {
214
            $status |= (ord($ret[$i]) ^ ord($hash[$i]));
215
        }
216
217
        return $status === 0;
218
    }
219
}
220
221
222
0 ignored issues
show
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
223