我们如何防止 MySQL 的 SQL 注入?
Posted
技术标签:
【中文标题】我们如何防止 MySQL 的 SQL 注入?【英文标题】:How can we prevent SQL-Injection from MySQL? 【发布时间】:2020-02-10 17:08:29 【问题描述】:我们都知道,我们可以通过查询的 Prepared Statement 或 mysqli_real_escape_string() 函数来防止 php 中的 SQL 注入。但是如果我想从 MySQL 方面阻止它呢?你有什么主意吗?我怎样才能实现它?
【问题讨论】:
这不是可以从 MySQL 端停止的事情,问题是使用 sql 注入数据被格式化为看起来像实际命令。为每个应用创建一个单独的 sql 用户,以限制每次攻击/其他错误的表面 您需要为这个问题提供更多上下文。正如上面评论中所说,SQL注入本质上属于SQL语言,而不是数据库服务器,所以不清楚你在问什么。 【参考方案1】:您可以使用存储过程来查询数据库。存储过程检查提供的数据类型和参数,如果不匹配,则不执行查询。
这是一个存储过程示例,您可以使用它在 mysql 中插入记录 -
DELIMITER $$
CREATE PROCEDURE book_Insert (
in title varchar(30),
in isbn varchar(30),
out bookID tinyint(3) unsigned
)
BEGIN
insert into books (title, isbn)
values(title, isbn);
set bookID =last_insert_id();
END $$
【讨论】:
Select 查询呢?【参考方案2】:正如@Ferrybig 的评论所说,在 MySQL 方面,无法确定 SQL 查询是合法的还是 SQL 注入的结果。
假设数据库服务器接收到这个查询:
SELECT col1, col2, col3 FROM MyTable WHERE account_id = 1
UNION SELECT user, password, NULL FROM mysql.user
这看起来很可疑。为什么应用程序要读取所有密码,并将其附加到我们希望看到的查询中?很有可能这是一次黑客攻击。
另一个例子:
SELECT col1, col2, col3 FROM MyTable WHERE account_id = 1
OR account_id = 473
这是合法的吗?或者它是非法的?是否为应该有权读取帐户 473 数据的用户执行查询?你怎么知道?在 MySQL 端,无论是不是 SQL 注入的结果,查询看起来都是一样的。
可能是下面这样的 PHP 代码,容易受到 SQL 注入的影响(这不是 PHP 的失败,因为类似的易受攻击的代码可以用任何编程语言编写):
$sql = "SELECT col1, col2, col3 FROM MyTable WHERE account_id = " . $_GET['id'];
如果攻击者导致输入参数为:"1 OR account_id = 473"
关键是,一旦查询在应用程序中被格式化并提交给 MySQL,MySQL 就无法告诉如何它是如何格式化的。 MySQL 只能相信代码的开发人员确实以安全的方式格式化了查询。
阻止非法查询的一种方法是使用Web Application Firewall (WAF) 类型,您设计该类型以识别合法输入并阻止非法请求。换句话说,您需要使用白名单或一组模式对 WAF 进行编程,以识别安全请求。此列表对于每个应用程序都是唯一的,因此您需要非常熟悉该应用程序。对应用的任何修改都可能需要您更新 WAF 的白名单。
WAF 通常是 http 层的代理,以防止非法请求到达 Web 应用程序。还有代理解决方案来保护应用程序和数据库之间的请求。您对代理进行编程以识别预期的 SQL 查询,并阻止任何具有意外术语的查询。会
数据库防火墙的一个例子是https://www.oracle.com/database/technologies/security/audit-vault-firewall.html
它们并不完美。他们可能会阻止您想要允许的查询。而且它们不适用于在存储过程中运行的动态查询。
最终,您应该在应用程序代码中建立安全的编程标准。每当您将不安全的数据与 SQL 查询结合使用时,请使用查询参数。
【讨论】:
【参考方案3】:你可以使用 假设你输入了一个参数 $bookID
DELIMITER $$
CREATE PROCEDURE `spGetBook`(
in bookID int)
BEGIN
SELECT *
FROM categories
where bookID=bookID;
END $$
【讨论】:
我没有投反对票,但您应该知道不要将过程参数命名为与您要比较的列相同的名称。以上是关于我们如何防止 MySQL 的 SQL 注入?的主要内容,如果未能解决你的问题,请参考以下文章