SQL 注入类型是什么
按回显方式,SQL 注入可分为报错注入、联合查询注入、布尔盲注与时间盲注。类型只决定攻击者用什么方式把数据取出来,并不改变根因——根因始终是用户输入被拼接进 SQL 语句。因此防御手段对四类完全一致:参数化查询(预编译),再加统一错误处理与响应差异收敛。
基本信息
| 影响范围 | 所有拼接 SQL 的应用,含存储过程与动态排序、表名拼接 |
|---|---|
| 分类依据 | 回显方式(报错 / 结果集 / 布尔差异 / 时间差异) |
| 根治手段 | 参数化查询 + 白名单校验无法参数化的位置 |
| 辅助手段 | 关闭详细报错、统一错误页、限速与慢查询监控 |
类型与特征
| 类型 | 回显特征 | 防御要点 |
|---|---|---|
| 报错注入 | 数据库错误信息随页面返回 | 关闭详细报错,统一错误页 |
| 联合查询 | 页面有查询结果展示位 | 参数化后该路径消失 |
| 布尔盲注 | 页面真假状态差异可辨 | 响应差异收敛(状态码/长度一致) |
| 时间盲注 | 响应时间随条件变化 | 超时与慢查询监控,参数化根治 |
错误处理配置示意(PHP)
错误处理配置示意(PHP)
// 生产环境关闭详细报错,错误进日志
ini_set('display_errors', '0'); # 页面不返回数据库细节
error_reporting(E_ALL); # 但内部仍完整记录
ini_set('log_errors', '1'); # 错误写入日志供排查
ini_set('error_log', '/var/log/php/error.log'); # 指定日志路径,避免写进 Web 目录参数化写法对照
参数化写法对照
# 错误:字符串拼接,任何输入都能改变语义
cur.execute("SELECT * FROM users WHERE name = '" + name + "'")
# 正确:占位符传参,输入永远只是数据
cur.execute("SELECT * FROM users WHERE name = %s", (name,))
# 无法参数化的位置(排序字段、表名)必须用白名单枚举,不要靠转义典型使用场景
- 渗透测试报告编写:说明发现方式与可复现证据,便于开发定位同名参数
- 代码审计:优先排查字符串拼接点、动态排序字段与报表拼接 SQL
- WAF 与日志规则:按盲注的「低速高频、同源相似请求」特征设计检测
- 修复验收:对同一参数用四类手法复测,确认没有任何一类仍有回显路径
- 培训与开发规范:把参数化写进代码评审清单,比事后扫一遍更有效
盲注类通常慢速低频,日志中表现为同一来源对同一接口的大量相似请求;如果只依赖「是否报错」来判定,很容易漏掉它们。
参数化解决数据位,不解决结构位:排序字段、表名、字段名无法用占位符,必须用白名单枚举,否则仍存在注入。