我目前正在使用mysqli php扩展程序。
传统上我使用mysqli_real_escape_string来逃避用户输入。但是,我正在考虑更改代码(希望尽可能少的步骤)来使用预准备语句。
我想明确这一点 - 如果我使用预准备语句来绑定我的所有变量,我可以确信sql注入是不可能的吗? (并完全免除mysqli_real_escape_string?)
由于
答案 0 :(得分:5)
如果正确绑定所有变量,可以大大降低SQL注入的风险。如果您动态创建SQL,仍然可以获取SQL注入,例如:
'SELECT * FROM ' . $tablename . ' WHERE id = ?'
但如果你避免这样的事情,你就不会有问题。
答案 1 :(得分:5)
说到安全性,如果正确绑定或格式化变量,两种方法之间没有区别。
绑定只是更简单,因为它只能用于任何情况,而转义不能(因此,你必须转换一些变量而不是转义/引用)。
另外,请记住,没有绑定或转义可以使标识符安全。因此,如果您必须在查询中使用字段名称或运算符,则必须使用在脚本中硬编码的值。
答案 2 :(得分:3)
以下是我对该主题的高级别观点。
使用动态SQL字符串时,您依赖于转义函数正常工作。不幸的是,情况并非总是如此,正如在这个(不可否认的旧)例子中可以看到的那样:
http://dev.mysql.com/doc/refman/5.0/en/news-5-0-22.html
一旦数据值被转义,SQL字符串就必须由数据库服务器进行解析和编译。如果转义函数没有正确完成其工作,或者发现了一个聪明的新SQL注入攻击,服务器可能会将数据误认为是SQL语句。
如果使用带参数的预准备语句,则首先解析和编译该语句。执行时,数据值与编译语句组合在一起。这将SQL逻辑与数据值分开 - 混淆两个应该永远不会发生的机会。
所以,是的,您可以免除mysqli_real_escape_string
,但我不会说使用带参数的预准备语句会导致SQL注入无法进行。它使得它变得更加困难,但与mysqli_real_escape_string
错误一样,我想总是有可能一个尚未发现(或新创建的)错误会使看似不可能的错误成为可能。