且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

我们如何防止来自 MySQL 的 SQL 注入?

更新时间:2023-02-05 21:23:48

正如@Ferrybig 的评论所说,在 MySQL 方面,没有办法确定 SQL 查询是合法的还是 SQL 注入的结果.

As the comment from @Ferrybig says, on the MySQL side there's no way to be sure that an SQL query is legitimate or the result of SQL injection.

假设数据库服务器收到这个查询:

Suppose the database server receives this query:

SELECT col1, col2, col3 FROM MyTable WHERE account_id = 1 
UNION SELECT user, password, NULL FROM mysql.user

这看起来很可疑.为什么应用程序要读取所有密码,并将其附加到我们希望看到的查询中?这很有可能是一种黑客行为.

This looks pretty suspicious. Why would the app want to read all passwords, and append it to the query we expect to see? There's a strong chance this is an attempt at hacking.

另一个例子:

SELECT col1, col2, col3 FROM MyTable WHERE account_id = 1
OR account_id = 473

这合法吗?还是违法?查询是否为应该有权读取帐户 473 的数据的用户执行?你怎么知道?在 MySQL 方面,无论是否是 SQL 注入的结果,查询看起来都完全一样.

Is this legitimate? Or is it illicit? Is the query executed for a user who should have privileges to read data for account 473? How can you know? On the MySQL side, the query looks exactly the same whether it was the result of SQL injection or not.

它可能是像下面这样的 PHP 代码,它容易受到 SQL 注入攻击(这不是 PHP 的失败,因为类似的易受攻击的代码可以用任何编程语言编写):

It might have been code like the following PHP, which is vulnerable to SQL injection (this is not a failing of PHP, because similar vulnerable code can be written in any programming language):

$sql = "SELECT col1, col2, col3 FROM MyTable WHERE account_id = " . $_GET['id'];

如果攻击者导致输入参数为:"1 OR account_id = 473"

If the attacker caused the input parameter to be: "1 OR account_id = 473"

关键是,一旦查询在应用程序中格式化并提交到 MySQL,MySQL 就无法告诉如何格式化它.MySQL 只能相信代码的开发者确实以安全的方式格式化了查询.

The point is, once the query is formatted in the app and submitted to MySQL, MySQL can't tell how it was formatted. MySQL can only trust that the developer of the code did format the query in a safe way.

阻止非法查询的一种方法是使用一种网络应用程序防火墙 (WAF) 您设计用于识别合法输入并阻止不合法的请求.换句话说,您需要使用白名单或一组模式对 WAF 进行编程以识别安全请求.此列表对于每个应用程序都是唯一的,因此您需要非常熟悉该应用程序.对应用的任何修改都可能需要您更新 WAF 的白名单.

One method of blocking illicit queries is by using a type of Web Application Firewall (WAF) that you design to recognize legitimate inputs and block requests that are not legitimate. In other words, you need to program the WAF with a whitelist or set of patterns to recognize safe requests. This list will be unique for each app, so you need to be very familiar with the app. Any modification to the app may require you to update the WAF's whitelist.

WAF 通常是 http 层的代理,以防止非法请求到达 Web 应用程序.还有代理解决方案来保护应用程序和数据库之间的请求.您对代理进行编程以识别哪些 SQL 查询是预期的,它会阻止任何具有意外术语的查询.它会

The WAF is typically a proxy at the http layer, to prevent illicit request from reaching the web app. There are also proxy solutions to protect the request between the app and the database. You program the proxy to recognize which SQL queries are expected, and it blocks any queries that have unexpected terms. It would

数据库防火墙的一个例子是https://www.oracle.com/database/technologies/security/audit-vault-firewall.html

An example of a database firewall is https://www.oracle.com/database/technologies/security/audit-vault-firewall.html

它们并不完美.他们可能会阻止您想要允许的查询.它们不适用于在存储过程中运行的动态查询.

They aren't perfect. They may block queries you want to allow. And they don't work for dynamic queries run in stored procedures.

最终,您应该在应用程序代码中建立安全的编程标准.将不安全数据与 SQL 查询结合使用时,请使用查询参数.

Ultimately, you should just establish safe programming standards in your application code. Use query parameters whenever you combine unsafe data with your SQL queries.