所以我读了几篇关于绑定的文章,老实说,虽然我理解我努力看到真正价值的好处。好处很明显,但我无法理解现实世界的例子。
有人可以向我展示一个简单的查询,用户可以在其中输入一个值,然后在可以发生 SQL 注入的地方提交它,然后向我展示绑定如何避免这种情况。这应该非常清楚发生了什么。
我显然是 PDO 的新手,正在从标准 MySql 语句过渡。
假设它只需要涉及用户输入是否正确,否则我们可以跳过绑定?
所以我读了几篇关于绑定的文章,老实说,虽然我理解我努力看到真正价值的好处。好处很明显,但我无法理解现实世界的例子。
有人可以向我展示一个简单的查询,用户可以在其中输入一个值,然后在可以发生 SQL 注入的地方提交它,然后向我展示绑定如何避免这种情况。这应该非常清楚发生了什么。
我显然是 PDO 的新手,正在从标准 MySql 语句过渡。
假设它只需要涉及用户输入是否正确,否则我们可以跳过绑定?
查看我的演示文稿SQL Injection Myths and Fallacies。
或者观看我介绍它的网络研讨会录音:http ://www.percona.com/webinars/2012-07-25-sql-injection-myths-and-fallacies (免费,但需要注册)。
我展示了几个例子,如下所示:
假设您有一个允许用户更改密码的页面,并且您希望用户使用如下 URL 访问它:
http://example.com/changepass.php?acctid=1234 &pass=xyzzy
(当然,他们通常会使用 POST 请求,但为了简单说明,让我们使用这种 GET 格式。)
在该页面的脚本中,您有如下 SQL 更新语句:
UPDATE Accounts
SET password = SHA2('$password')
WHERE account_id = $account_id
现在,如果恶意用户巧妙地设置参数怎么办,如下所示:
http://example.com/changepass.php?acctid=1234 OR TRUE &pass= xyzzy'), admin=('1
然后您的 SQL 将最终运行此语句:
UPDATE Accounts SET password = SHA2(' xyzzy'), admin=('1 ') <br> WHERE account_id = 1234 OR TRUE
这将设置密码,但还会在表中设置另一列以授予用户管理员权限。WHERE 子句中的注入将更改应用于您站点中的所有用户,而不仅仅是登录的用户。
参数的值是:一个参数在 SQL 表达式中始终被视为一个值。
也就是说,即使您为该参数传递的字符串恰好包含利用注入的 SQL 语法,使用参数也意味着它不能被解释为单个字符串或数值以外的任何内容。所以它不能终止字符串,或者包含括号或OR
其他任何会修改 SQL 语句的语法或语义的东西。
所以通过使用绑定参数,它更像是这样的:
UPDATE Accounts SET password = SHA2(' xyzzy\'), admin=(\'1 ') <br> WHERE account_id = ' 1234 OR TRUE '
密码可能看起来很有趣,里面有空格和引号,但它不会改变你的 SQL 的含义。WHERE 子句将使用该字符串的整数值,即 1234。
回复您的评论:
我没有跟踪代码的每一行,但我相信它使 SQL 语句字符串与每个执行阶段的值分开。在某些时候,SQL 被解析,然后以某种内部方式(不是人类可读的文本)表示;然后将参数值组合到此中,但它们被迫成为单个句法元素。关键是,它们是在解析查询后组合在一起的,因此参数值无法更改语法。
一个例外:通用查询日志将值插入到原始 SQL 字符串中,以便在给定执行时记录查询及其参数。但是这个组合查询字符串没有被执行。