1
0
mirror of https://github.com/php/doc-en.git synced 2026-03-23 23:32:18 +01:00

Use random salt, precise examples, mention prepared statements, warn before addslashes()

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@325889 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
Jakub Vrana
2012-05-29 22:30:54 +00:00
parent 6b70471032
commit 6bfcf7d9af

View File

@@ -120,19 +120,21 @@
<?php
// storing password hash
// $random_chars retrieved e.g. using /dev/random
$query = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
pg_escape_string($username), crypt($password, '$2a$07$usesomesillystringforsalt$'));
pg_escape_string($username),
pg_escape_string(crypt($password, '$2a$07$' . $random_chars . '$')));
$result = pg_query($connection, $query);
// querying if user submitted the right password
$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';",
pg_escape_string($username), crypt($password, '$2a$07$usesomesillystringforsalt$'));
$result = pg_query($connection, $query);
$query = sprintf("SELECT pwd FROM users WHERE name='%s';",
pg_escape_string($username));
$row = pg_fetch_assoc(pg_query($connection, $query));
if (pg_num_rows($result) > 0) {
echo 'Welcome, $username!';
if ($row && crypt($password, $row['pwd']) == $row['pwd']) {
echo 'Welcome, ' . htmlspecialchars($username) . '!';
} else {
echo 'Authentication failed for $username.';
echo 'Authentication failed for ' . htmlspecialchars($username) . '.';
}
?>
@@ -225,8 +227,7 @@ insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
<?php
$query = "SELECT id, name, inserted, size FROM products
WHERE size = '$size'
ORDER BY $order LIMIT $limit, $offset;";
WHERE size = '$size'";
$result = odbc_exec($conn, $query);
?>
@@ -269,20 +270,20 @@ $query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
</programlisting>
</example>
But a malicious user sumbits the value
<literal>' or uid like'%admin%'; --</literal> to <varname>$uid</varname> to
<literal>' or uid like'%admin%</literal> to <varname>$uid</varname> to
change the admin's password, or simply sets <varname>$pwd</varname> to
<literal>"hehehe', admin='yes', trusted=100 "</literal> (with a trailing
space) to gain more privileges. Then, the query will be twisted:
<literal>hehehe', trusted=100, admin='yes</literal> to gain more
privileges. Then, the query will be twisted:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
// $uid == ' or uid like'%admin%'; --
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";
// $uid: ' or uid like '%admin%
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%';";
// $pwd == "hehehe', admin='yes', trusted=100 "
$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE
// $pwd: hehehe', trusted=100, admin='yes
$query = "UPDATE usertable SET pwd='hehehe', trusted=100, admin='yes' WHERE
...;";
?>
@@ -315,8 +316,8 @@ $result = mssql_query($query);
<?php
$query = "SELECT * FROM products
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD'--";
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD' --%'";
$result = mssql_query($query);
?>
@@ -376,6 +377,14 @@ $result = mssql_query($query);
Use always customized users with very limited privileges.
</simpara>
</listitem>
<listitem>
<simpara>
Use prepared statements with bound variables. They are provided
<link linkend="pdo.prepared-statements">by PDO</link>,
<link linkend="mysqli.quickstart.prepared-statements">by MySQLi</link>
and by other libraries.
</simpara>
</listitem>
<listitem>
<simpara>
Check if the given input has the expected data type. <acronym>PHP</acronym> has
@@ -391,7 +400,7 @@ $result = mssql_query($query);
<listitem>
<para>
If the application waits for numerical input, consider verifying data
with <function>is_numeric</function>, or silently change its type
with <function>ctype_digit</function>, or silently change its type
using <function>settype</function>, or use its numeric representation
by <function>sprintf</function>.
<example>
@@ -415,16 +424,15 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d
</listitem>
<listitem>
<simpara>
Quote each non numeric user supplied value that is passed to the
If the database layer doesn't support binding variables then
quote each non numeric user supplied value that is passed to the
database with the database-specific string escape function (e.g.
<function>mysql_real_escape_string</function>,
<function>sqlite_escape_string</function>, etc.). If a database-specific
string escape mechanism is not available, the
<function>addslashes</function> and <function>str_replace</function>
functions may be useful (depending on database type).
See <link linkend="security.database.storage">the first example</link>.
As the example shows, adding quotes to the static part of the query
is not enough, making this query easily crackable.
<function>sqlite_escape_string</function>, etc.).
Generic functions like <function>addslashes</function> are useful only
in a very specific environment (e.g. MySQL in a single-byte character
set with disabled <varname>NO_BACKSLASH_ESCAPES</varname>) so it is
better to avoid them.
</simpara>
</listitem>
<listitem>