历史上,我一直使用
mysql_real_escape_string()
用于从最终触及数据库的用户派生的所有输入。
现在我已经完全转换为MySQLi并且我正在使用带有绑定参数的准备查询,我是否有效地消除了SQL注入攻击的可能性?
我说我不再需要
mysql_real_escape_string()?
这是我的理解和我的项目的基础: http://sourceforge.net/projects/mysqldoneright/files/Base/MysqlDoneRight-0.23.tar.gz/download
这不是我想弄错的事情,虽然现在我已经发布了它,它也可能会影响其他人。
现在,所有用户提供的输入都将以bind_parms结尾 准备阶段提供的查询是静态的。
答案 0 :(得分:13)
是。使用准备好的查询将转义参数。
答案 1 :(得分:6)
这不是那么简单。您可以使用绑定参数,而不是仅将应用程序变量插入到SQL表达式中,而不是文字值:
$sql = "SELECT * FROM MyTable WHERE id = ".$_GET["id"]; // not safe
$sql = "SELECT * FROM MyTable WHERE id = ?"; // safe
但是,除了字面值之外,如果你需要将查询的一部分动态化呢?
$sql = "SELECT * FROM MyTable ORDER BY ".$_GET["sortcolumn"]; // not safe
$sql = "SELECT * FROM MyTable ORDER BY ?"; // doesn't work!
该参数将始终被解释为值,而不是列标识符。您可以使用ORDER BY 'score'
运行查询,该查询与ORDER BY score
不同,并且使用参数将被解释为前者 - 常量字符串'score'
,而不是命名列中的值score
。
因此,在很多情况下,您必须使用动态SQL并将应用程序变量插入到查询中以获得所需的结果。在这些情况下,查询参数无法帮助您。你仍然需要保持警惕并采取防御措施来防止SQL注入漏洞。
没有框架或数据访问库可以为您完成此工作。您始终可以构造包含SQL注入漏洞的SQL查询字符串,并在数据访问库看到SQL查询之前执行此操作。那怎么知道什么是故意的,什么是缺陷呢?
以下是实现安全SQL查询的方法:
过滤输入。跟踪插入SQL查询的所有变量数据。使用输入filters删除非法字符。例如,如果您期望一个整数,请确保输入被约束为整数。
转义输出。此上下文中的输出可以是您发送到数据库服务器的SQL查询。您知道可以对值使用SQL查询参数,但列名称呢?您需要一个标识符的转义/引用功能,就像旧的mysql_real_escape_string()
用于字符串值一样。
代码评论。让某人成为第二双眼睛并查看您的SQL代码,以帮助您找到您忽略使用上述两种技术的地方。
答案 2 :(得分:1)
将参数绑定到预准备语句时,它会自动转义数据,因此在发送之前不应将其转义。双重逃避通常是一件坏事。至少,它会在以后使用额外的转义字符产生难看的结果。