撇号和反斜杠悖论

时间:2014-02-15 04:07:27

标签: php mysql sql regex

我一直在困惑这一段时间,并且终于屈服于在这里寻求帮助。

我有一个用于抓取的preg_match脚本,它匹配循环中的不同变量并将它们存储在一个数组中,最后发布到SQL表中。只要变量包含撇号,就会出现问题。

以下是我抓取和整理数据的方法

for($i = 0; $i < count($bokse[0]); $i++){
    preg_match_all("/title=\"Mere information om (.+?)\"/sim", $bokse[0][$i], $name, PREG_SET_ORDER);
    $laeger[$i]['navn'] = stripslashes(mysql_real_escape_string($name[0][1]));
}

现在,我抓住的东西,mysql_escaped和剥离的值可以是:

**Michael D'Angelo** [NOTICE THE APOSTROPHE]

如果我想将此回显到页面,我可以成功地正确回显D'angelo(使用撇号)

echo $laeger[$i]['navn'];

会给我Michael D'Angelo

但是当把它存储在数据库中时,我遇到了一个悖论;我可以选择将其存储为Michael D\'Angelo

或者存储D,并收到SQL错误。

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'angelo'
(..........blablabv...............)

以下是我存储数据的方式

mysql_query("INSERT INTO table (name) VALUES ('".$laeger[$i]['navn']."'")");  or die(mysql_error());

根据我是否使用striplashes,我要么搞乱查询,要么弄乱结果(使用bachflash)。 FML。

2 个答案:

答案 0 :(得分:5)

没有悖论。你只是不明白逃脱是如何运作的。

如果你有:

INSERT INTO sometable (fieldname) VALUES ('Michael D\'Angelo')

反斜杠将 NOT 输入数据库的磁盘存储。它被数据库的SQL解析器剥离了。同样,当您从表中检索名称时,它不会被转义。您将Michael D'Angelo返回给您的客户。

您所拥有的是SQL注入攻击漏洞 - 允许包含SQL元字符的原始用户提供的数据出现在SQL上下文中,而不考虑这些元字符。

这就是为什么(对于老派代码)像mysql_real_escape_string()这样的东西会逃避提供的字符串中的所有SQL元字符,因此它们变成纯文本而不再是“元”。

答案 1 :(得分:1)

正如您在评论中指出的那样,接受的答案对您没有任何帮助。它只会提前知道你要抓取哪些数据才能正常工作,这样你就可以将反斜杠放在正确的位置,但当然你事先并不知道所以你需要一个能在运行时运行的解决方案。 MySQL为您提供了这样的解决方案。

解决问题的答案是将插入更改为:

mysql_query("INSERT INTO table (name) VALUES ('".mysql_real_escape_string($laeger[$i]['navn'])."'")");

或者我喜欢这样做,即使它是非标准的:

 mysql_query("INSERT INTO table set name='".mysql_real_escape_string($laeger[$i]['navn'])."'");

我认为编码更容易,阅读也更容易。

对于我自己的工作,我创建了一个名为“dbstring”的“辅助函数”,它包含了转义函数周围的撇号,这使得所有内容都更紧凑,更易读,可在数据库之间传输,并且可以防止SQL注入攻击。