PHP中的魔术引号

时间:2008-10-21 00:50:28

标签: php security magic-quotes

根据PHP manual,为了使代码更具可移植性,他们建议使用以下内容来转义数据:

if (!get_magic_quotes_gpc()) {
    $lastname = addslashes($_POST['lastname']);
} else {
    $lastname = $_POST['lastname'];
}

我还将进行其他验证检查,但上述严格来说,在逃避数据方面有多安全?我还看到在PHP 6中将不推荐使用魔术引号。这将如何影响上述代码?我宁愿不依赖于像mysql_real_escape_string()这样的特定于数据库的转义函数。

12 个答案:

答案 0 :(得分:25)

魔术引言本来就被打破了。它们旨在清理PHP脚本的输入,但不知道如何使用该输入,就无法正确清理。如果有的话,最好检查魔术引号是否已启用,然后在$ _GET / $ _ POST / $ _ COOKIES / $ _ REQUEST上调用stripslashes(),然后在某处使用它时清理变量。例如。 urlencode()如果您在URL中使用它,htmlentities()如果您将其打印回网页,或者如果您将数据库驱动程序存储到数据库中则使用数据库驱动程序的转义函数。请注意,那些输入数组可能包含子数组,因此您可能需要编写一个函数可以递归到子数组中以去除这些斜杠。

PHP man page on magic quotes同意:

  

“此功能已被弃用为   PHP 5.3.0和从PHP开始删除   5.4.0。非常不鼓励依赖此功能。魔术行情是一个   自动逃脱的过程   传入数据到PHP脚本。它的   喜欢用魔术引号编码   关闭并转而逃避数据   运行时,根据需要。“

答案 1 :(得分:17)

魔术引号是一个设计错误。它们的使用与保持你的理智是不相容的。

我更喜欢:

if (get_magic_quotes_gpc()) {
   throw new Exception("Turn magic quotes off now!");
}

不要编写代码以兼容固有损坏的设置。而是通过使用代码FAIL FAST来保护他们的使用。

答案 2 :(得分:6)

我在我网站的头文件中使用以下代码来反转magic_quotes的效果:

<?php

// Strips slashes recursively only up to 3 levels to prevent attackers from
// causing a stack overflow error.
function stripslashes_array(&$array, $iterations=0) {
    if ($iterations < 3) {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                stripslashes_array($array[$key], $iterations + 1);
            } else {
                $array[$key] = stripslashes($array[$key]);
            }
        }
    }
}

if (get_magic_quotes_gpc()) {
    stripslashes_array($_GET);
    stripslashes_array($_POST);
    stripslashes_array($_COOKIE);
}

?>

然后我可以编写其余的代码,好像magic_quotes从未存在过。

答案 3 :(得分:2)

“我宁愿不依赖于像mysql_real_escape_string()这样的特定于数据库的转义函数”

然后使用类似PDO的内容。但无论如何,你必须扭转魔法引号所造成的伤害。

答案 4 :(得分:2)

在您的代码上添加PHP 5.2或更高版本的要求并使用filter APIfilter_*函数直接访问原始输入数据(它们不会触及$_POST等),因此它们完全不受magic_quotes_gpc的影响。

然后这个例子:

if (!get_magic_quotes_gpc()) {
    $lastname = addslashes($_POST['lastname']);
} else {
    $lastname = $_POST['lastname'];
}

可以成为这个:

$lastname = filter_input(INPUT_POST, 'lastname');

答案 5 :(得分:1)

是的,这不是最好的方式而不是最安全的方式。逃避最好与您逃避的内容相关。如果要存储在mysql数据库中,请使用mysql_real_escape_string,它考虑了其他语言环境,字符集。对于HTML,htmlentities。用于代码,escapeshellcmd,escapeshellarg。是的,如果启用魔术引号,您可能需要首先使用stirpslashes。但最好不要依赖它或使用它。

答案 6 :(得分:0)

关于使用特定于数据库的转义函数,您非常需要。我发现只使用addslashes()在MySQL的极少数情况下失败。您可以编写一个要转义的函数来确定您正在使用的DB,然后使用适当的转义函数。

答案 7 :(得分:0)

你可以试试这个:

if (get_magic_quotes_gpc()) { 
          $_REQUEST = array_map('stripslashes', $_REQUEST); 
          $_GET = array_map('stripslashes', $_GET);
          $_POST = array_map('stripslashes', $_POST);
          $_GET = array_map('stripslashes', $_COOKIES);

    }

答案 8 :(得分:0)

“我宁愿不依赖于像mysql_real_escape_string()这样的特定于数据库的转义函数”

也可以欺骗addslashes,看看这篇文章:

http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

答案 9 :(得分:0)

您的示例代码是向后的,您应该执行以下操作:

if (get_magic_quotes_gpc()) {
  $lastname = stripslashes($_POST['lastname']);
} else {
  $lastname = $_POST['lastname'];
}

请注意,这会使您的输入数据处于“原始”状态,就像用户输入的那样 - 没有额外的反斜杠,并且可能会加载SQL注入和XSRF攻击 - 而这正是您想要的。然后,确保始终使用以下其中一项:

  • echo变量转换为HTML时,请将其包装在htmlentities()
  • 将其放入mysql时,请使用预准备语句或至少mysql_real_escape_string()
  • echo将变量放入Javascritpt代码时,请使用json_encode()

Joel Spolsky在Making Wrong Code Look Wrong

中有一些很好的开端建议

答案 10 :(得分:0)

刚刚在PHP manual pages上发现这一点,看起来像是一种非常聪明的剥离方式(处理键和值......):

if (get_magic_quotes_gpc())
{
    $_GET = json_decode(stripslashes(json_encode($_GET, JSON_HEX_APOS)), true);
    $_POST = json_decode(stripslashes(json_encode($_POST, JSON_HEX_APOS)), true);
    $_COOKIE = json_decode(stripslashes(json_encode($_COOKIE, JSON_HEX_APOS)), true);
    $_REQUEST = json_decode(stripslashes(json_encode($_REQUEST, JSON_HEX_APOS)), true);
    ini_set('magic_quotes_gpc', 0);
}

答案 11 :(得分:0)

准备好PDOMysqli语句是防止SQL注入的更好方法。

但是,如果您要为每个SQL查询迁移基于Magic Quotes的遗留代码,您可以参考yidas/php-magic-quotes在PHP 5.4以上版本的环境中实现Magic Quotes。

  

https://github.com/yidas/php-magic-quotes