在PHP中使用预准备语句/存储过程时,如何保护自己免受SQL注入?

时间:2011-06-30 10:14:48

标签: php mysql security pdo sql-injection

我一直在研究如何最好地防止PHP / mysql中的sql注入,而不仅仅是使用mysqli / mysql真正的转义,因为阅读此Is mysql_real_escape_string enough to Anti SQL Injection?

我见过这个非常好的帖子How can I prevent SQL injection in PHP?

我用来在桌面/内部工具上做很多ms sql server的东西,我们总是编写存储过程来防止这种情况所以我在PHP / mysql中使用PDO http://php.net/manual/en/pdo.prepared-statements.php

在上面有一行:

  

不需要引用准备语句的参数;驱动程序自动处理这个。如果应用程序专门使用预准备语句,开发人员可以确保不会发生SQL注入(但是,如果查询的其他部分是使用非转义输入构建的,则仍然可以进行SQL注入)。

我一直认为PDO可以防止sql注入攻击,所以有人可以从安全的角度提供PDO不足的实例吗?

2 个答案:

答案 0 :(得分:3)

您仍然可以从内部使用PREPARE语法(在MySQL中)创建动态SQL语句的存储过程中获取SQL注入。

这些需要非常小心,必要时使用QUOTE()。

理想情况下,我们不需要在存储例程中使用PREPARE,但在某些情况下,它很难避免:

  • 在MySQL 5.5之前,LIMIT子句不能使用非常量值。
  • IN()子句中使用的列表不能(合理地)参数化,因此如果使用此模式,则需要使用动态SQL
  • 有时需要使用动态生成的ORDER BY子句。

如果需要使用PREPARE,我建议按优先顺序排列:

  • 如果某些东西是INT类型(等),它不容易受到SQL注入的影响,您可以将该值放入查询中而不会出现问题(例如,对于LIMIT)
  • 字符串值可以在EXECUTE之前放入@variable,也可以传入EXECUTE子句
  • 需要检查列表值(例如IN())的有效性。
  • 最后,QUOTE()可用于引用字符串值,这在某些情况下很有用

答案 1 :(得分:1)

您使用的结构(存储过程,预处理语句等)不是决定性的,而是您是否在任何时候使用未经检查的用户输入将SQL连接在一起。例如,您可以在存储过程中执行动态SQL,在这种情况下,危险仍然存在。

最简单的方法(从注入避免的角度来看)是使用带有限制变量的SP或PS:不需要检查它们,因为它们将被识别为在预定义占位符内的值。 / p>