edit-不应将其标记为重复项。问题不在于如何防止SQL注入攻击(我已经在其他地方使用了准备好的语句),而是与MySQL为何杀死一个恶意注入的查询有关。
我正在测试具有连接的MySQL数据库的Web应用程序,特别是寻找潜在的SQL注入问题,并想知道在这种特定情况下如何防止此类攻击。
一个页面根据唯一的ID号从数据库中加载一个人的信息,该ID号可通过该页面的URL看到。显然,这本身就是一个问题-我可以将ID从“?id = 2”更改为“?id = 3”以从数据库中加载新记录-但我更关心的问题是此刻是基于URL的攻击,目的是在预期查询的顶部执行“不良”查询。
预期查询如下所示:... where person.ID="10" and person.ID = notes.ID and ...
通过更改URL,我可以关闭正在寻找ID的参数,并执行另一个潜在的恶意查询,如下所示:
... ?id=10"; drop table person; select * from notes where ID=" ...
这将导致执行以下查询:
... select * from person, notes where id="10"; drop table person; select * from notes where ID="" and ...
我已经能够获取此恶意查询集,以将其打印(回显)到我的网页上,因此我知道这是一个漏洞。但是,当我尝试在MySQL中执行此确切查询时,它会挂起几秒钟,然后完全退出MySQL,并显示响应“杀死”,没有进一步的解释。
那么,我的问题是什么导致MySQL终止了该恶意查询并退出?这似乎是一项安全功能,但我不知道会是什么-那些查询本身就很好。如果有人遇到过类似情况,我还会对除“杀死”之外缺少错误消息感到困惑。
答案 0 :(得分:0)
MySQL对您显示的情况的唯一保护是默认情况下,MySQL的查询接口不会执行多个语句。用;
分隔语句只会导致语法错误。
但是,多查询是一个选项,并且取决于客户端,该选项可能已启用。
PDO默认情况下启用多查询。我可以运行以下命令,它将插入两行:
$pdo->query("insert into foo set id = 1; insert into foo set id = 2");
但是,如果尝试使用预处理语句(禁用模拟的prepare),它将失败:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare("insert into foo set id = ?; insert into foo set id = ?");
如果启用了例外,则会引发异常:
PHP致命错误:未被捕获的PDOException:SQLSTATE [42000]:语法错误或访问冲突:1064您的SQL语法有错误;请参阅附录A。检查与您的MySQL服务器版本相对应的手册以获取正确的语法,以在“插入foo set id =?中插入”附近使用在第1行
Mysqli仅对使用mysqli_multi_query()函数执行的查询启用多查询。因此,如果您在代码中未使用multi_query(),则很安全。
此外,如果您确实使用查询参数(我看到您的评论中确实使用了查询参数),那么您也很安全,因为即使该参数包含任何欺骗查询的尝试,它也不会起作用。
使用准备好的语句时,参数不会简单地连接到SQL查询中。这是许多开发人员的误解。
将参数与SQL语法分开,直到之后解析SQL。然后,在MySQL执行查询时组合参数,但是对于任何尝试进行SQL注入的用户来说,修改查询的解析方式为时已晚。
这就是为什么查询参数是一种保护应用程序免受SQL注入的好方法。