MySQL 是否具有针对基于 URL 的攻击的内置注入攻击保护?
Does MySQL have built-in injection attack protections against URL-based attacks?
编辑 - 这不应被标记为重复。问题不是如何防止 SQL 注入攻击(我已经在其他地方使用准备好的语句),而是与为什么 MySQL 杀死恶意注入的查询有关。
我正在测试一个连接了 MySQL 数据库的 Web 应用程序,专门寻找潜在的 SQL 注入问题,并想知道如何在这种特定情况下防止此类攻击。
一个页面根据唯一的ID号从数据库中加载一个人的信息,通过页面的URL可见。显然,这本身就是一个问题 - 我可以简单地将 ID 从“?id=2”更改为“?id=3”以从数据库加载新记录 - 但我更关心的问题是目前是基于 URL 的攻击,在预期查询之上执行 "bad" 查询。
预期查询如下所示:... 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 并返回 "Killed" 并且没有进一步的解释。
那么我的问题是,是什么导致 MySQL 终止此恶意查询并退出?这似乎是一项安全功能,但我不知道它会是什么——这些查询本身就完全没问题。如果有人遇到过类似情况,我也对 "Killed" 之外缺少错误消息感到困惑。
MySQL 对您显示的情况的唯一保护是默认情况下,MySQL 的查询接口不执行多条语句。用 ;
分隔语句只会导致语法错误。
但是,多查询是一个选项,根据客户端的不同,该选项可能已启用。
PDO 默认启用多查询。我可以 运行 以下内容,它会插入两行:
$pdo->query("insert into foo set id = 1; insert into foo set id = 2");
但是,如果您尝试使用准备语句(禁用模拟准备),它会失败:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare("insert into foo set id = ?; insert into foo set id = ?");
如果您启用了异常,这将引发异常:
PHP Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into foo set id = ?' at line 1
Mysqli 仅对使用 mysqli_multi_query() 函数执行的查询启用多查询。因此,如果您不在代码中使用 multi_query(),那么您是安全的。
此外,如果您确实使用了查询参数(我看到您的评论说您确实使用了查询参数),您也是安全的,因为即使参数包含任何欺骗查询的企图,它也不会不工作。
当您使用准备好的语句时,参数不会简单地连接到 SQL 查询中。这是很多开发者的误区。
参数与 SQL 语法分开,直到 SQL 被解析。然后参数被合并为 MySQL 执行查询,但是对于任何试图 SQL 注入修改查询将被解析的方式来说已经太晚了。
这就是为什么查询参数是保护您的应用免受 SQL 注入攻击的好方法。
编辑 - 这不应被标记为重复。问题不是如何防止 SQL 注入攻击(我已经在其他地方使用准备好的语句),而是与为什么 MySQL 杀死恶意注入的查询有关。
我正在测试一个连接了 MySQL 数据库的 Web 应用程序,专门寻找潜在的 SQL 注入问题,并想知道如何在这种特定情况下防止此类攻击。
一个页面根据唯一的ID号从数据库中加载一个人的信息,通过页面的URL可见。显然,这本身就是一个问题 - 我可以简单地将 ID 从“?id=2”更改为“?id=3”以从数据库加载新记录 - 但我更关心的问题是目前是基于 URL 的攻击,在预期查询之上执行 "bad" 查询。
预期查询如下所示:... 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 并返回 "Killed" 并且没有进一步的解释。
那么我的问题是,是什么导致 MySQL 终止此恶意查询并退出?这似乎是一项安全功能,但我不知道它会是什么——这些查询本身就完全没问题。如果有人遇到过类似情况,我也对 "Killed" 之外缺少错误消息感到困惑。
MySQL 对您显示的情况的唯一保护是默认情况下,MySQL 的查询接口不执行多条语句。用 ;
分隔语句只会导致语法错误。
但是,多查询是一个选项,根据客户端的不同,该选项可能已启用。
PDO 默认启用多查询。我可以 运行 以下内容,它会插入两行:
$pdo->query("insert into foo set id = 1; insert into foo set id = 2");
但是,如果您尝试使用准备语句(禁用模拟准备),它会失败:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare("insert into foo set id = ?; insert into foo set id = ?");
如果您启用了异常,这将引发异常:
PHP Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into foo set id = ?' at line 1
Mysqli 仅对使用 mysqli_multi_query() 函数执行的查询启用多查询。因此,如果您不在代码中使用 multi_query(),那么您是安全的。
此外,如果您确实使用了查询参数(我看到您的评论说您确实使用了查询参数),您也是安全的,因为即使参数包含任何欺骗查询的企图,它也不会不工作。
当您使用准备好的语句时,参数不会简单地连接到 SQL 查询中。这是很多开发者的误区。
参数与 SQL 语法分开,直到 SQL 被解析。然后参数被合并为 MySQL 执行查询,但是对于任何试图 SQL 注入修改查询将被解析的方式来说已经太晚了。
这就是为什么查询参数是保护您的应用免受 SQL 注入攻击的好方法。