SQL注入(SQL Injection)是一种通过将恶意的SQL代码插入查询语句中来攻击数据库的技术。它可以绕过身份验证、检索敏感数据、修改数据库内容,甚至执行数据库命令。
以下是常见的SQL注入类型和示例:
1. 基于字符串的SQL注入
攻击者通过在输入字段中插入恶意的SQL代码来操纵查询。
- 示例:
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
- 如果输入:
username: admin' --
password: 任意值
最终查询变成:
SELECT * FROM users WHERE username = 'admin' -- ' AND password = '任意值';
`--` 表示注释,后面的SQL部分将被忽略,攻击者可以绕过密码验证。
2. 基于联合查询的SQL注入(Union-Based Injection)
通过使用 `UNION` 操作符,将额外的查询结果与合法查询结果合并。
- 示例:
SELECT id, username, password FROM users WHERE id = 1;
- 如果输入:
1 UNION SELECT null, version(), null;
- 最终查询变为:
SELECT id, username, password FROM users WHERE id = 1 UNION SELECT null, version( ), null;
这样可以获取数据库版本等敏感信息。
3. 基于错误的SQL注入(Error-Based Injection)
利用数据库返回的错误信息来推断数据结构或内容。
- 示例:
SELECT * FROM users WHERE id = 1 AND 1=CONVERT(int, (SELECT @@version));
如果注入不合法的数据类型或语法错误,数据库会返回错误信息,从而泄露内部信息。
4. 布尔盲注(Boolean-Based Blind Injection)
当应用不显示错误消息时,攻击者通过提交不同的输入,根据响应是否变化来判断查询的结果。
- 示例:
SELECT * FROM users WHERE id = 1 AND SUBSTRING(username, 1, 1) = 'a';
攻击者可以通过逐字符猜测字段内容,利用布尔值判断真伪。
5. 时间盲注(Time-Based Blind Injection)
攻击者通过使用延时函数(如 `SLEEP()` 或 `WAITFOR DELAY`),根据响应时间判断查询是否为真。
- 示例:
SELECT * FROM users WHERE id = 1 AND IF(SUBSTRING(username, 1, 1) = 'a', SLEEP(5), 0);
如果用户名第一个字符是 `a`,查询会延迟5秒返回,从而让攻击者确定条件为真。
6. 批量查询注入(Stacked Queries Injection)
某些数据库允许在同一个查询中执行多条SQL语句。
- 示例:
1; DROP TABLE users; --
这条语句首先执行合法查询,然后执行删除操作。
7. 二次注入(Second-Order Injection)
攻击者在初次输入无效后,将恶意SQL代码存储在数据库中,等待系统在某个时间点执行。
- 示例:
攻击者将恶意输入存入字段,当应用程序再次调用这些数据时,SQL注入攻击被执行。
8. 内联注入(Inline Comment Injection)
利用注释符号干扰和篡改SQL查询。
- 示例:
' OR 1=1 /*'
这段输入会使SQL查询的逻辑被破坏。
防护措施
1. 使用预编译语句和参数化查询*
:如在PHP中使用PDO或在Java中使用PreparedStatement。
2. 输入验证和清理:对输入数据进行严格验证,避免特殊字符。
3. 使用ORM框架:通过ORM框架进行数据库交互,减少手写SQL的机会。
4. 最小权限原则:限制数据库用户权限,防止执行敏感操作。
5. 安全配置:禁用多语句查询、限制错误信息暴露。
SQL注入是一个严重的安全问题,了解并防范这些攻击方式对保障系统安全至关重要。