目录
2.2.1 显式回显注入(Union-Based Injection)
2.3.2 预处理语句注入(Prepared Statement Injection)
一、SQL 注入基础概念
1.1 什么是 SQL 注入(SQL Injection)
SQL 注入是一种常见的 Web 安全漏洞攻击手段,攻击者通过在应用程序的输入字段中插入恶意 SQL 语句,篡改原本合法的 SQL 查询逻辑,从而非法获取、篡改或删除数据库中的数据,甚至控制数据库服务器。
核心原理:应用程序对用户输入的合法性校验不足,导致输入的恶意数据被当作 SQL 语句的一部分执行。
二、SQL 注入攻击分类与典型案例
2.1 基于注入位置的分类
2.1.1 数字型注入
特征:注入点参数为数字类型,SQL 语句中使用 WHERE id = ${input}
等形式。
案例:
假设存在查询语句:
SELECT * FROM users WHERE id = ${user_id};
若用户输入 1 OR 1=1 --
,拼接后变为:
SELECT * FROM users WHERE id = 1 OR 1=1 --;
--
是 SQL 注释符,后续语句被注释,导致查询绕过条件,返回所有用户数据。
2.1.2 字符串型注入
特征:注入点参数为字符串类型,SQL 语句中使用 WHERE name = '${input}'
等形式,需闭合单引号或双引号。
案例:
查询语句:
SELECT * FROM products WHERE name = '${product_name}';
用户输入 ' OR '1'='1
,拼接后变为:
SELECT * FROM products WHERE name = '' OR '1'='1';
'1'='1'
恒成立,导致查询返回所有产品数据。
2.2 基于回显结果的分类
2.2.1 显式回显注入(Union-Based Injection)
特征:利用 UNION
、UNION ALL
等联合查询语句,将恶意查询结果与正常结果合并返回,通过页面直接获取数据。
案例:
判断字段数:输入 1 UNION SELECT 1,2,3 --
,若页面回显 2
和 3
,说明查询结果有 3 个字段。
获取敏感信息:
1 UNION SELECT user(), database(), version() --
返回当前数据库用户、数据库名和版本号。
2.2.2 盲注(Blind SQL Injection)
特征:页面不直接回显查询结果,需通过构造条件语句(如 IF
函数),根据响应时间或布尔值(如页面是否正常)推断数据。
分类:
- 布尔盲注:通过
AND
/OR
构造条件,判断结果是否为真。
案例:输入1' AND LENGTH(database())>5 --
,若页面正常,说明数据库名长度大于 5。 - 时间盲注:利用
SLEEP()
、WAITFOR DELAY
等函数,根据响应延迟判断条件是否成立。
案例(MySQL):sql
1' AND IF((SELECT COUNT(*) FROM users)>10, SLEEP(5), 0) --
若用户表数据超过 10 条,页面延迟 5 秒返回。
2.3 基于攻击手法的分类
2.3.1 堆叠查询注入(Stacked Queries)
特征:通过分号 ;
分隔多条 SQL 语句,执行多条命令(如删除表、添加用户)。
案例:
输入 1; DROP TABLE users; --
,拼接后执行:
SELECT * FROM posts WHERE id = 1; DROP TABLE users; --
直接删除用户表。
2.3.2 预处理语句注入(Prepared Statement Injection)
特征:攻击目标为未正确使用参数化的预处理语句(如拼接参数而非绑定参数)。
案例:
错误用法(PHP-PDO):
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = '$email'"); // 未使用参数绑定
$stmt->execute();
若 $email
为 ' OR 1=1 --
,则拼接后绕过验证。
2.3.3 宽字节注入
特征:利用数据库字符集特性(如 GBK),通过 %df
等宽字节字符绕过转义符(如 \
)。
案例:
正常输入 %df'
,数据库解析为 �'
(一个宽字符),使转义符 \
失效,从而闭合 SQL 语句。
2.4 特殊场景注入
2.4.1 HTTP 头部注入
特征:攻击位置为 HTTP 请求头(如 Cookie、User-Agent)。
案例:
Cookie 值为 user_id=1' OR 1=1 --
,后端查询时拼接为:
SELECT * FROM users WHERE id = '1' OR 1=1 --';
获取所有用户信息。
2.4.2 ORM 框架注入
特征:攻击目标为 ORM(对象关系映射)框架生成的非安全查询语句。
案例(Hibernate):
错误写法:
String hql = "FROM User WHERE username = '" + username + "'";
Query query = session.createQuery(hql);
若 username
为 ' OR 1=1 --
,则生成恶意 HQL 语句。
三、SQL 注入攻击的危害
- 数据泄露:窃取用户隐私(如账号、密码、银行卡信息)。
- 数据篡改:修改交易记录、用户权限等关键数据。
- 服务瘫痪:通过
DROP TABLE
、TRUNCATE
等语句删除数据库表,导致系统崩溃。 - 权限提升:利用注入获取数据库管理员权限,进一步控制服务器。
- 跳板攻击:以数据库为跳板,渗透至内部网络其他系统。
四、SQL 注入防御策略
4.1 输入验证与过滤
- 严格限制输入类型:仅允许合法字符(如数字、字母、特定符号),禁止特殊字符(如
';--
、UNION
)。 - 使用白名单过滤:例如,用户 ID 只能为正整数,使用正则表达式校验:
python
import re if not re.match(r'^\d+$', user_input): raise ValueError("Invalid input")
4.2 使用参数化查询(核心防御手段)
- 预编译语句(Prepared Statements):将 SQL 语句与参数分离,数据库会将参数视为纯文本。
案例(Python-PyMySQL):python
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
- ORM 框架安全使用:避免拼接 SQL,使用 ORM 提供的查询构造器。
案例(Django ORM):python
User.objects.filter(id=user_id) # 自动参数化
4.3 最小权限原则
- 为数据库用户分配最小必要权限:
- 应用程序使用的数据库账户不具备
DROP TABLE
、CREATE USER
等高危权限。 - 区分管理员账户与普通账户权限。
- 应用程序使用的数据库账户不具备
4.4 输出编码与转义
- 对输出到页面的数据进行 HTML 编码,防止 XSS 与 SQL 注入结合攻击。
- 使用数据库提供的转义函数(如 PHP 的
mysqli_real_escape_string
)。
4.5 安全开发实践
- 代码审计:定期扫描代码中的 SQL 拼接风险(如使用静态代码分析工具 SonarQube)。
- 安全测试:通过 OWASP ZAP、SQLMap 等工具进行漏洞扫描。
- 日志监控:记录数据库操作日志,及时发现异常查询(如高频
UNION
、SELECT *
)。
五、实战防御案例:参数化查询 vs 注入攻击
5.1 不安全代码(拼接 SQL)
# 错误示例(Python Flask)
@app.route("/user")
def get_user():
user_id = request.args.get('id')
conn = sqlite3.connect('db.sqlite')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE id = " + user_id) # 未参数化
result = cursor.fetchone()
return jsonify(result)
攻击方式:输入 id=1 OR 1=1
,返回所有用户数据。
5.2 安全代码(参数化查询)
# 正确示例(Python Flask + SQLAlchemy)
@app.route("/user")
def get_user():
user_id = request.args.get('id')
result = db.session.execute(
text("SELECT * FROM users WHERE id = :id"),
{"id": user_id}
).fetchone()
return jsonify(result)
防御原理::id
为参数占位符,user_id
作为纯文本传递,避免 SQL 拼接。
六、总结
SQL 注入是 Web 应用最危险的漏洞之一,但通过规范的开发流程和安全实践(如参数化查询、输入过滤),完全可以有效防御。开发者需时刻牢记:永远不要信任用户输入,将安全编码融入每一行代码。
参考资源:
- OWASP SQL 注入攻击指南
- SQLMap 官方文档
- 《Web 渗透测试实战》——SQL 注入章节
通过深入理解各类注入手法与防御策略,能够显著提升应用程序的安全性,守护数据资产免受攻击威胁。