3

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 in my PHP source code...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JiminP
  • 2,136
  • 19
  • 26
  • 1
    Magic_quotes wasn't intended as security feature, but merely to make SQL work out of the box. [(1)](http://www.php.net/manual/phpfi2.php#msql_support) By accident it was secure around PHP2/PHP3 because most used databases didn't work with multibyte charsets. But unless you ensure you receive just ASCII for your application/DB connection, you will have to adapt that. – mario Apr 27 '11 at 09:37

4 Answers4

3

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.

Emil Vikström
  • 90,431
  • 16
  • 141
  • 175
  • 2
    +1 You can also try adding `php_flag magic_quotes_gpc Off` to your .htaccess file to turn off this feature (for that specific dir the .htaccess is in). You can also turn it off in php.ini or httpd.conf if you have access to those (in this case it will be turned off on the whole server). – kapa Apr 27 '11 at 09:42
  • [Magic quotes](https://www.php.net/manual/en/security.magicquotes.php) were removed as of PHP 5.4.0. Perhaps it is time for an update? – Peter Mortensen Nov 29 '19 at 15:50
3

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:

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);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alix Axel
  • 151,645
  • 95
  • 393
  • 500
  • I think your first coding block is unnecessarily slow and also uninterpretable. JSON encoding and decoding plus regular expressions is not especially fast. The second solution, from the manual, is much cleaner (IMHO) and doesn't mess around with strange hacks. – Emil Vikström Apr 27 '11 at 10:37
  • @Emil: I don't think it's uninterpretable... `json_encode()` with the `JSON_HEX_APOS` and `JSON_HEX_QUOT` flags makes sure single and double quotes are escaped, since control chars are also escaped we use the regex to add an extra slash and then remove the superfluous ones via `stripslashes()`, after that `json_decode()` should decode the super global keys and values back to an array. As for the speed, I haven't tested it, but JSON functions are quite fast now, I would be surprised if there was any major difference. – Alix Axel Apr 27 '11 at 10:53
  • [Magic quotes](https://www.php.net/manual/en/security.magicquotes.php) were removed as of PHP 5.4.0. Perhaps it is time for an update (***without*** "Edit", or "Updated 2019-11-29", or similar (this belongs in edit summaries))? – Peter Mortensen Nov 29 '19 at 15:46
1

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
0

mysqli_real_escape_string() is a good start.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Flask
  • 4,966
  • 1
  • 20
  • 39