SQL 注入中的“参数化查询/准备语句”如何比转义用户输入更好
Posted
技术标签:
【中文标题】SQL 注入中的“参数化查询/准备语句”如何比转义用户输入更好【英文标题】:How "parameterized queries/prepared statements" better in SQL injection than escaping user input 【发布时间】:2018-05-18 16:23:09 【问题描述】:有很多articles 告诉使用parametrized queries
而不是escaping user input
。但没有显示任何示例。我想知道一个真实的例子,其中“参数化查询/准备好的语句”可以防止 SQL 注入,而转义用户输入则不能。你能举一个例子,parameterized query
在用户输入的查询仍然包含特殊字符造成伤害时防止 SQL 注入攻击?例如,parameterized queries
可以处理但escaping user input
无法处理的查询
Query like = ' or 1=1--
//我想知道有没有类似的查询,“参数化查询/准备好的语句”可以防止SQL注入,但“转义用户输入”不能
【问题讨论】:
OWASP 项目https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Primary_Defenses 【参考方案1】:问:能否举个例子,当用户对查询的输入仍然包含特殊字符造成伤害时,参数化查询可以防止 SQL 注入攻击?
答:代码中有一些多字节字符攻击没有正确考虑字符集,导致转义机制出现漏洞。 (“转义字符串”认为它正在处理特定编码的字符串,但实际字节采用不同的编码,并偷偷地将单引号滑入 SQL 文本。)
但我真的不认为这是使用绑定占位符准备语句的最有力论据。
一个强有力的论点是,当我们查看代码时,我们看到的是静态 SQL 文本,而不是动态生成的......
$sql = 'SELECT fee, fi FROM fo WHERE fum = ?';
$dbh->prepare($sql);
我们看到该代码,我们查看该 SQL 文本...我们立即认识到,SQL 文本将与我们看到的不同。没有。我们不必查看代码中的其他任何地方;我们在两条线上看到它。
当我们看到这个时:
$sql = "SELECT fee, fi FROM fo WHERE fum = $fumval";
这是双引号,正在进行变量解释。 $fumval
是否保证 安全 可以包含在 SQL 文本中,$fumval
是从哪里来的? $fumval 周围应该有单引号,还是我们保证它已经用单引号括起来了?
好的,也许在那之前有一行:
$fumval = $dbh->quote($unsafe_fumval);
如果该行不在生成 SQL 文本的正上方,我们需要检查...我们是否保证 $fumval 是安全的?
重点是... SQL 是动态构造的。如果这样做可能会更好:
$sql = 'SELECT fee, fi FROM fo WHERE fum = ' . $dbh->quote($unsafe_fumval);
对于一个简单的陈述,可能是一个六个中的六个。但是当 SQL 语句变得更大,涉及多个表和几十个列引用和值时,动态构造变得更难验证其中没有任何问题。
是否可以使用动态生成的 SQL 和对值的“转义字符串”处理来编写安全代码?是的。
是否可以编写易受攻击的代码,将预准备语句与动态生成的 SQL 文本一起使用?是的。
这确实是 static SQL 文本的模式,通过 bind 占位符 提供的值传递让我们物有所值...我们可以识别为不易受 SQL 注入攻击的方式。
【讨论】:
以上是关于SQL 注入中的“参数化查询/准备语句”如何比转义用户输入更好的主要内容,如果未能解决你的问题,请参考以下文章