【问题标题】:Why do prepared statements protect against injections?为什么准备好的语句可以防止注入?
【发布时间】:2012-06-28 07:56:45
【问题描述】:

我已经对准备好的语句有了基本的了解,并且我知道它们可以防止 SQL 注入攻击。但我还没有理解为什么他们可以防止上述攻击。我知道有人问过类似的问题,但我没有找到完全令人满意的答案。

示例 - 非常不安全的代码
所以这里我们有了与数据库通信的最基本方式:

$query = "SELECT * FROM users where id=$username";

在没有任何保护的情况下,用户可以输入恶意代码,从而“欺骗”数据库引擎执行破坏性查询:

$username = "1; DROP TABLE users;"
SELECT * FROM users where id=1; DROP TABLE users;

我不明白准备好的语句如何设法“过滤掉”此类数据。它背后的机制是什么不会诱使数据库生成如上所示的 SQL 查询?是像转义某些字符一样简单,例如上例中的分号,还是更复杂?

如果我要像示例中那样进行精确的注入攻击,但通过准备好的语句运行它,什么样的命令字符串会到达数据库引擎?

【问题讨论】:

标签: php mysql sql-injection


【解决方案1】:

基本上,如果你使用标准的无类型参数绑定,你会得到

SELECT * FROM users where id='1; DROP TABLE users;'

这会在数据库中出错,但不会造成任何伤害。

请理解,这和跑步不一样

SELECT * FROM users where id='$username' 

带有适当转义的$username - 它发生在数据库访问堆栈的较低层。

【讨论】:

    【解决方案2】:

    Prepared statements 不只是添加文本,它们将其作为数据发送,并让数据库单独处理它。因为实际上数据库实际上并不使用 SQL 语句,而是使用它们的“编译”版本。

    我不太清楚我是否清楚,但这在于查询是如何发送到数据库的。

    【讨论】:

      【解决方案3】:

      准备好的语句通常被构建为使用参数绑定。真正隔离此类攻击的是参数绑定。您可以使用参数绑定而不使用准备好的语句。

      prepared statements 提供的第二级保护是每个语句都是一个语句(因此使用; 从一个语句中创建两个语句是行不通的)。

      作为一般规则,为了免受注入攻击,准备好的语句必须从非来自任何外部输入的数据中准备。

      【讨论】:

        猜你喜欢
        • 2015-11-08
        • 2023-03-08
        • 2012-01-05
        • 2012-06-19
        • 2012-08-07
        • 2012-07-12
        相关资源
        最近更新 更多