SQL 注入原理与防御

从参数拼接、SQL 解析、盲注和报错注入开始理解 SQL 注入原理,并总结预处理语句、参数化查询、最小权限和日志审计等防御方法。

写在前面:合法学习边界

本文讲解 SQL 注入的原理与防御。所有示例都用于理解漏洞形成过程,不代表你可以对真实网站、数据库或企业系统实施攻击。漏洞验证必须在自建靶场、公司授权测试环境或明确书面授权的目标上完成。未经授权访问、篡改、读取数据库数据可能触犯《网络安全法》《数据安全法》《个人信息保护法》和《刑法》相关规定。

一、为什么 SQL 注入一直是高频漏洞

SQL 注入的本质是:程序把用户输入拼接到 SQL 语句里,数据库把这段输入当成 SQL 代码执行了。

很多开发者写查询时会这样想:

1
SELECT * FROM users WHERE username = 'admin'

如果后端直接拼接用户输入:

1
SELECT * FROM users WHERE username = '" + username + "'"

而用户输入:

1
admin' OR '1'='1

最终可能变成:

1
SELECT * FROM users WHERE username = 'admin' OR '1'='1'

数据库会把它理解成一个永远为真的条件,从而绕过登录判断。

安全学习的关键不是记住 ' OR 1=1,而是理解:

1
输入没有被当作数据,而被当成了逻辑或命令的一部分

二、SQL 注入的常见类型

1. 基于错误的注入

数据库返回错误信息,泄露表名、字段名、SQL 结构甚至系统路径。

例子:

1
Unknown column 'id' in 'field list'

这种报错通常说明数据库参数、字段或查询结构有问题,但真正利用需要授权环境。

2. 基于布尔盲注

页面只有两种状态,比如成功/失败、有数据/无数据。攻击者通过构造条件逐位猜解信息。

例如:

1
2
id=1 AND 1=1
id=1 AND 1=2

通过页面差异判断条件真假。

3. 基于时间盲注

页面没有明显差异,但响应时间不同。常见做法是构造慢查询条件。

例如:

1
id=1 AND SLEEP(5)

这类技术需要谨慎理解,真实使用只能在授权靶场。

4. 基于联合查询的注入

当查询结果被直接展示在页面上,攻击者可能尝试把其他表的数据带进页面。

典型结构是:

1
UNION SELECT table_name FROM information_schema.tables

这是理解原理时的常见写法,不能直接在真实网站执行。

三、为什么很多系统会中招

SQL 注入往往不是单点问题,而是工程习惯问题。

常见原因包括:

1
2
3
4
5
6
拼接 SQL
没有统一输入处理
没有最小权限数据库账号
错误信息直接暴露给用户
没有 WAF 或日志审计
代码复用多个查询模板

尤其是老系统、后台系统、导出功能、搜索功能和订单查询功能,都容易出现输入直接进入查询的地方。

影响与危害

SQL 注入能造成:

1
2
3
4
登录绕过
数据库数据泄露(脱库)
篡改数据
执行系统命令(配合堆叠查询/存储过程)

严重时直接导致整个数据库甚至服务器沦陷。风险等级:高到严重。

四、防御思路

1. 参数化查询

这是最有效、最通用的防御方式。核心思想是把参数交给驱动,而不是拼接字符串。

伪代码:

1
2
query = "SELECT * FROM users WHERE username = ?"
params = [username]

不要把用户输入直接拼进 SQL 文本。

2. 输入校验

输入校验能减少风险,但不应成为唯一防线。正确做法是:

1
2
3
4
限制格式
限制长度
限制枚举值
按业务校验类型

但真正的安全边界应该在数据库访问层。

3. 最小权限

数据库账号不要直接给管理员权限。只给应用真正需要的权限,例如:

1
2
3
SELECT
INSERT
UPDATE

不要给:

1
2
3
4
5
GRANT
FILE
SUPER
DROP
ALTER

4. 错误信息控制

生产环境不要把原始 SQL 错误、堆栈和数据库结构直接展示给用户。应该记录服务端日志,对用户返回友好错误。

5. 审计和监控

关注这些现象:

1
2
3
4
参数中频繁出现 SQL 关键字
大量 500 错误
登录失败后请求模式异常
导出接口被频繁调用

修复

1
2
3
4
5
改用参数化查询/预处理语句(最根本)
数据库账号最小权限,禁用 FILE/SUPER 等
关闭错误信息回显
对历史代码排查拼接 SQL
修复后复测:拼接 payload 不再生效

五、SQL 注入在报告中的正确写法

好的报告需要说清证据、影响和建议。

示例:

1
2
3
发现:搜索参数 q 的值会拼接到 SQL 查询,错误页面显示原始 SQL 片段。
风险:可能导致登录绕过、数据泄露、条件查询异常。
建议:改为参数化查询;限制数据库账号权限;关闭错误信息泄露;补充 WAF 与日志审计。

不要只写“存在 SQL 注入风险”,要有验证依据。

六、小结

SQL 注入的核心不是工具,而是输入与查询边界。凡是用户输入最终进入 SQL 的地方,都要优先采用参数化查询、最小权限和错误控制。理解了这个边界,XSS、SSRF、文件上传和日志分析也会更容易看懂。