Does PHP auto escape quotes in a string which is passed by GET or POST?
Consider file a.php
:
<?php
echo $_GET['a'];
?>
a.php?a=abcd'
prints abcd\'
.
I think PHP auto escape quotes, but I couldn't find a document about this.
Is it true? Because I want to make sure - I'm quite lazy, so I didn't prevent SQL injection开发者_JAVA百科 in my PHP source code...
It depends on whether magic_quotes_gpc
in On
or not on your php.ini
configuration file.
This configuration directive was introduced to help developers secure themselves against SQL injection attacks. If you don't know what they are, I suggest you read the Wikipedia entry very carefully.
The thing is, relying only on magic_quotes
is insecure and unpredictable, and this feature will also be removed in future PHP versions. The best way to secure against SQL injection is to either use prepared statements (with PDO or MySQLi) or use the specific escaping function for your database:
PDO::quote()
mysql_escape_string()
or better yetmysql_real_escape_string()
However, if magic_quotes
is on and you try to escape your input data chances are you will get a double escaped string (which is not good), to counteract this we usually detect if magic_quotes
is On
and, if it is, remove the added slashes via stripslashes()
.
Some do this before calling the database escaping function / method, but personally I prefer to do it upon page load since this will make the data much more consistent and less prone to errors. If you're using PHP 5.3+ the following snippet should disable magic_quotes
:
if (get_magic_quotes_gpc() === 1)
{
$_GET = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_GET, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
$_POST = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_POST, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
$_COOKIE = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_COOKIE, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
$_REQUEST = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_REQUEST, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
}
If you are running an older version of PHP, the PHP Manual has a fairly good snippet too:
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
PHP does this if magic_quotes_gpc is active in the configuration. This functionality is deprecated and will disappear in the future. It's not good (actually, it's outright stupid) to rely on deprecated functionality when writing new code.
Note that magic quotes is not enough to protect against SQL injections since it doesn't handle all character sets correctly. I recommend that you invert the magic quoting and use mysql_real_escape_string (or similar in other database extensions) instead.
You need to update your code to do proper escaping of your SQL input. Or even better, use PDO so you can pass query arguments separately from the query.
While PHP has magic_quotes_gpc
, it's disabled by default and will be removed in PHP 6. Besides that, it's a horrible mess leading to potentially insecure or faulty code and thus it's better to remove automatically added quotes if get_magic_quotes_gpc()
is true
.
mysqli_real_escape_string() is a good start.
精彩评论