简体   繁体   English

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

[英]How do protect yourself against SQL injection when using prepared statements/store procedures in PHP?

I've been looking at how best to protect against sql injection in PHP/mysql beyond just using the mysqli/mysql real escape since reading this Is mysql_real_escape_string enough to Anti SQL Injection?自从阅读本文以来,我一直在研究如何最好地防止 PHP/mysql 中的 sql 注入,而不仅仅是使用 mysqli/mysql 真正的转义

I have seen this very good thread How can I prevent SQL injection in PHP?我见过这个非常好的线程如何防止 PHP 中的 SQL 注入?

I use to do alot of ms sql server stuff on the desktop/internal tools, we always wrote stored procedures to protect against this so I read up on the equivalent in PHP/mysql using PDO http://php.net/manual/en/pdo.prepared-statements.php我曾经在桌面/内部工具上做很多 ms sql 服务器的东西,我们总是编写存储过程来防止这种情况,所以我使用 PDO Z80791B3AE7002CB88C246876D9A /en 阅读了 PHP/mysql 中的等价物。 /pdo.prepared-statements.php

In the above there is the line:在上面有一行:

The parameters to prepared statements don't need to be quoted;准备好的语句的参数不需要引用; the driver automatically handles this.驱动程序会自动处理这个。 If an application exclusively uses prepared statements, the developer can be sure that no SQL injection will occur (however, if other portions of the query are being built up with unescaped input, SQL injection is still possible).如果应用程序专门使用准备好的语句,开发人员可以确定不会发生 SQL 注入(但是,如果查询的其他部分是使用非转义输入构建的,SQL 注入仍然是可能的)。

I've been lead to believe that PDO do protect against sql injection attacks so can anyone provide a instance where PDO isnt sufficient from a security standpoint?我一直相信 PDO 确实可以防止 sql 注入攻击,所以任何人都可以提供从安全角度来看 PDO 不够的实例吗?

You can still get SQL injections from stored procedures which are internally using the PREPARE syntax (in MySQL) to create dynamic SQL statements.您仍然可以从内部使用 PREPARE 语法(在 MySQL 中)创建动态 SQL 语句的存储过程中获取 SQL 注入。

These need to be done with extreme care, using QUOTE() as necessary.这些需要非常小心地完成,必要时使用 QUOTE()。

Ideally, we should not need to use PREPARE in stored routines, but in certain cases it becomes very difficult to avoid:理想情况下,我们不需要在存储例程中使用 PREPARE,但在某些情况下,它变得非常难以避免:

  • Prior to MySQL 5.5, the LIMIT clause cannot use non-constant values.在 MySQL 5.5 之前,LIMIT 子句不能使用非常量值。
  • Lists used in an IN() clause cannot be (sensibly) parameterised, so you need to use dynamic SQL if this pattern is used IN() 子句中使用的列表不能(明智地)参数化,因此如果使用此模式,则需要使用动态 SQL
  • It is sometimes desirable to use dynamically generated ORDER BY clauses.有时需要使用动态生成的 ORDER BY 子句。

etc ETC

In the case where it is necessary to use PREPARE, then I would recommend, in order of preference:在需要使用 PREPARE 的情况下,我会按优先顺序推荐:

  • If something is an INT type (etc) it is not susceptible to SQL injection, and you can place the value into the query without a problem (eg for LIMIT)如果某物是 INT 类型(等),则它不易受到 SQL 注入的影响,您可以毫无问题地将值放入查询中(例如对于 LIMIT)
  • String values can be placed into an @variable before the EXECUTE, or passed in to the EXECUTE clause字符串值可以放在 EXECUTE 之前的 @variable 中,或者传递给 EXECUTE 子句
  • List-values (for example for IN()) need to be checked for validity.需要检查列表值(例如 IN())的有效性。
  • Finally, QUOTE() can be used to quote string values, which can be useful in some cases最后,QUOTE() 可用于引用字符串值,这在某些情况下很有用

It's not the structure you use (stored procedures, prepared statements etc.) that is decisive, but whether you are at any point concatenating SQL together using unchecked user input .决定性的不是您使用的结构(存储过程、准备好的语句等),而是您是否在任何时候使用未经检查的用户输入将 SQL 连接在一起。 For example, you can execute dynamic SQL from within a stored procedure, in which case the danger is still there.例如,您可以在存储过程中执行动态 SQL,在这种情况下危险仍然存在。

The easiest way (from the injection-avoidance point of view) is to use SPs or PSs with bound-in variables: these do not need to be checked as they will be recognized as values to go within a predefined placeholder.最简单的方法(从避免注入的角度来看)是使用带有绑定变量的 SP 或 PS:这些不需要检查,因为它们将被识别为预定义占位符内 go 的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM