PHP中的魔术引号

根据PHP手册 ,为了使代码更加便携,他们推荐使用类似于以下的方式来转义数据:

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

我还有其他的validation检查,但是要严格按照转义数据的安全程度来判断。 我也看到,魔术引号将在PHP 6中被弃用。这将如何影响上述代码? 我宁愿不必依赖数据库特定的转义函数,如mysql_real_escape_string()。

魔法语录天生就被打破了。 他们的目的是消毒PHP脚本的input,但不知道如何input将被使用,是不可能正确消毒。 如果有的话,最好检查是否启用了魔术引号,然后在$ _GET / $ _ POST / $ _ COOKIES / $ _ REQUEST上调用stripslashes(),然后在某处使用它的地方清理variables。 如urlencode(),如果你正在使用它的URL,htmlentities(),如果你打印回网页,或使用数据库驱动程序的转义函数,如果你要存储到数据库。 注意那些input数组可能包含子数组,所以您可能需要编写一个函数来recursion到子数组中去除那些斜线。

魔术引号上的PHP 手册页同意:

“这个特性自PHP 5.3.0开始已经被取消了,从PHP 6.0.0开始已经被取消了。依靠这个特性是非常不鼓励的。Magic Quotes是一个自动将input数据转义到PHP脚本的过程。引用closures,而是在运行时根据需要转义数据。“

魔术引号是一个devise错误。 他们的使用不符合保留您的理智。

我更喜欢:

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

不要编写与固有的破坏设置兼容的代码。 相反,捍卫自己的使用,让你的代码失败的快速 。

我在我的网站的头文件中使用以下代码来反转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从来没有存在过。

“我宁愿不必依赖数据库特定的转义函数,如mysql_real_escape_string()”

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

在您的代码中添加PHP 5.2或更高版本的要求,并使用filterAPI 。 filter_*函数直接访问原始input数据(它们不会触及$_POST等),所以它们完全不受magic_quotes_gpc影响。

那么这个例子:

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

可以成为这个:

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

对,这不是最好的办法,也不是最安全的。 逃逸最好是根据你逃跑的方式来完成的。 如果要存储在mysql数据库中,请使用mysql_real_escape_string,它考虑到其他语言环境,字符集。 对于HTML,htmlentities。 在代码中使用escapeshellcmd,escapeshellarg。 是的,如果魔法引号出现,你可能需要先动一下。 但最好不要指望或使用它。

关于使用数据库特定的转义函数,你几乎需要。 我发现刚刚使用addslashes()在MySQL的罕见情况下失败。 您可以编写一个函数来确定您正在使用哪个数据库,然后使用相应的转义函数。

你可以试试这个:

 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); } 

“我宁愿不必依赖数据库特定的转义函数,如mysql_real_escape_string()”

也可以欺骗以及检查这个职位:

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

你的示例代码是倒退的,你应该这样做:

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

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

  • 将variables回显为HTML时,将其封装在htmlentities()
  • 当把它放到mysql中时,至less要使用预处理语句或mysql_real_escape_string()
  • 当将variables回显成Javascritpt代码时,使用json_encode()

Joel Spolsky在制作错误代码错误方面有一些很好的开始build议

刚刚在PHP手册页上find了这个,看起来像一个非常聪明的方式来剥离EM(处理键和值…):

 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); } 

编写PDO和Mysqli语句是防止SQL注入的更好方法。

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

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