SQL 注入

SQL 注入利用 Web 应用无法验证用户输入的漏洞。黑客可以恶意地通过 Web 应用传递 SQL 命令,让后端数据库执行。

SQL 注入可以获取对数据库的未经授权的访问,或直接从数据库中检索信息。许多数据泄露都是由于 SQL 注入造成的。

Pie chart of most common vulnerabilities: SQL Injection is responsible for 50% of vulnerabilities, Cross Site Scripting is responsible for 42% of vulnerabilities, Source Code Disclosure is responsible for 7% of vulnerabilities.

原始来源

工作原理

Screenshot of the login form with username and password fields

在输入用户名和密码后,在 GUI 后面,SQL 查询的工作原理如下

sql
"SELECT Count(*) FROM Users WHERE Username=' " + txt.User.Text+" ' AND Password=' "+ txt.Password.Text+" ' ";

现在假设用户输入用户名:admin,密码:passwd123,那么在点击登录按钮后,SQL 查询将如下运行

sql
"SELECT Count(*) FROM Users WHERE Username=' admin ' AND Password=' passwd123 ' ";

如果凭据正确,则允许用户登录,这是一个非常简单的(因此不安全的)机制。黑客利用这种不安全性获取未经授权的访问。

黑客使用一个简单的字符串,称为“魔法字符串”,例如

用户名:*admin*

密码:*anything 'or'1'='1*

在点击登录按钮后,SQL 查询将如下工作

sql
"SELECT Count(*) FROM Users WHERE Username=' admin ' AND Password=' anything 'or'1'='1 ' ";

仔细看看上面的查询的密码部分。

Password=' anything 'or'1'='1 '

密码不是 'anything',因此 password=anything 的结果为 FALSE,但 '1'='1' 是一个 TRUE 语句,因此返回 TRUE 值。最终,由于 OR 运算符的存在,该值 (FALSE OR TRUE) 为 TRUE,因此身份验证成功绕过。仅仅因为一个简单的字符串(魔法字符串),整个数据库就被泄露了。

如何预防

在执行用户凭据查询之前,进行一些更改,如下所示

sql
$id = $_GET['id']

(1) $id = Stripslashes($id)

(2) $id = mysql_real_escape_String($id)

因此,由于 (1) 输入字符串中的每个单引号 (') 被替换为双引号 ("),并且由于 (2) 在每个 (') 之前添加 (/)。修改后的魔法字符串无法绕过身份验证,您的数据库仍然安全。

参见