文章目录
- [SQL 注入与盲注技术笔记(PHP + MySQL)](#SQL 注入与盲注技术笔记(PHP + MySQL))
-
- [一、从功能出发理解 SQL 注入的四种基本操作(CRUD)](#一、从功能出发理解 SQL 注入的四种基本操作(CRUD))
- 二、从"是否回显数据"引出盲注的必要性
-
- [1️⃣ SELECT 的特点](#1️⃣ SELECT 的特点)
- [2️⃣ INSERT / DELETE / UPDATE 的特点](#2️⃣ INSERT / DELETE / UPDATE 的特点)
- 核心转折点
- 三、盲注的本质与三种类型
-
- [1️⃣ 什么是盲注](#1️⃣ 什么是盲注)
- 四、三种盲注方式及其适用条件
- [五、实践建议:盲注中优先使用 OR 而不是 AND](#五、实践建议:盲注中优先使用 OR 而不是 AND)
- 六、三步走核心思想(非常重要)
- [七、CMS 实战案例分析](#七、CMS 实战案例分析)
- [八、DELETE / INSERT 注入的经验结论](#八、DELETE / INSERT 注入的经验结论)
- 九、最终总结(可背)
- [SQL 注入与盲注 ------ 思路导向型笔记](#SQL 注入与盲注 —— 思路导向型笔记)
-
-
[一、第一性原则:SQL 注入不是"技巧",而是"控制执行逻辑"](#一、第一性原则:SQL 注入不是“技巧”,而是“控制执行逻辑”)
-
- [1️⃣ 看到功能,先不要想"注入"](#1️⃣ 看到功能,先不要想“注入”)
-
- [情况 A:页面直接显示数据](#情况 A:页面直接显示数据)
- [情况 B:页面只显示"成功 / 失败"](#情况 B:页面只显示“成功 / 失败”)
-
[六、INSERT / DELETE / UPDATE 的思路差异](#六、INSERT / DELETE / UPDATE 的思路差异)
-
- INSERT
- [DELETE / UPDATE](#DELETE / UPDATE)
-
[七、为什么实战中经常"OR 比 AND 好用"](#七、为什么实战中经常“OR 比 AND 好用”)
-
- [AND 的隐含前提](#AND 的隐含前提)
- [OR 的优势](#OR 的优势)
-
1、首先通过功能实现引出SQL注入的四则基本操作
2、通过页面数据回显与否也就是select和其他三种关注点的不同引出 如果页面不回显数据就需要进行盲注,相较于直接的看到数据,需要用true/false来进行猜测
3、讲了三种盲注:布尔(页面响应有区分)、报错(die(mysql_error()))、时间盲注 以及其对应的适用条件
4、使用案例、新闻的增删改查来实验三种盲注
补充:在使用盲注时,最好使用or来代替and总结而言;盲注其实是在第三步也就是如何改变执行逻辑并得到结果处做文章
5、熊海cms做实例进行巩固
报错 => 容错处理 => 无法回显报错信息
在三步走中,要注意考虑你的数据输入进到了哪里,决定你输入改变逻辑的地方要注意到,比如字符型和数字型不一样
insert 注入
关键代码:"新增错误" + die(mysql_error);
payload:' and updatexml(1,concat(0x7e,(select database()),0x7e),1) and '
6、KKcms: delete 注入
使用bp来观察时间,发现让延迟1s,延迟了3s,让延迟3s,延迟了9s,无所谓,只要与正常情况有所区别即可在bp里面数据包的空格使用%20进行表示,因为和在浏览器中不同,没办法直接打空格 在进行数据库名的注入时,通过后端代码发现了单引号被添加了斜杠。那么就使用ord()函数将语句转换为 if(ord(left(database(),1))=107,sleep(5),sleep(0)) 不使用单引号
-


SQL 注入与盲注技术笔记(PHP + MySQL)
一、从功能出发理解 SQL 注入的四种基本操作(CRUD)
SQL 注入并不是"凭空存在"的,而是依附于功能:
| 功能 | SQL 操作 | 典型语句 |
|---|---|---|
| 查询 | SELECT | SELECT * FROM news WHERE id=$id |
| 新增 | INSERT | INSERT INTO news (字段) VALUES (数据) |
| 删除 | DELETE | DELETE FROM news WHERE id=$id |
| 修改 | UPDATE | UPDATE news SET title=$t WHERE id=$id |
结论:
只要用户输入参与了以上任意 SQL 语句拼接,且未做安全处理,就可能产生 SQL 注入。
二、从"是否回显数据"引出盲注的必要性
1️⃣ SELECT 的特点
- 查询结果可能直接显示在页面
- 可使用:
- 联合查询注入(UNION)
- 直接读取数据
2️⃣ INSERT / DELETE / UPDATE 的特点
- 通常不回显数据库数据
- 页面只显示:
- "新增成功"
- "删除成功"
- "操作失败"
👉 无法直接看到查询结果
核心转折点
当页面不回显数据 时,传统注入失效 → 必须使用 盲注
三、盲注的本质与三种类型
1️⃣ 什么是盲注
盲注:在注入过程中,数据库中的真实数据无法直接显示在页面,需要通过"间接方式"判断数据是否成立。
本质就是:
构造条件 → 改变执行逻辑 → 根据页面/时间/错误差异判断真假
四、三种盲注方式及其适用条件
1️⃣ 基于布尔的 SQL 盲注(Boolean-based)
原理
- 构造 TRUE / FALSE 条件
- 页面响应必须存在可区分差异
常用函数
length()
left()
substr() / mid()
ord() / ascii()
like
regexp
示例
and length(database())=7
and left(database(),1)='p'
and ord(left(database(),1))=112
适用条件
- 页面 对真/假结果有不同响应
- 无需报错、无需延时
2️⃣ 基于时间的 SQL 盲注(Time-based)
原理
- 条件成立 → 延迟
- 条件不成立 → 不延迟
- 通过响应时间判断真假
常用函数
if()
sleep()
示例
and sleep(5)
and if(1=1,sleep(5),0)
and if(ord(left(database(),1))=107,sleep(2),0)
适用条件
- 页面 无回显
- 无报错
- 但可观察请求时间(BP / curl)
👉 通用性最强
3️⃣ 基于报错的 SQL 盲注(Error-based)
原理
- 利用数据库函数主动制造错误
- 错误信息中携带敏感数据
常用函数
updatexml()
extractvalue()
floor()
示例
and updatexml(1,concat(0x7e,(select version()),0x7e),1)
适用条件
-
后端存在:
die(mysql_error()); -
数据库错误 直接回显到页面
五、实践建议:盲注中优先使用 OR 而不是 AND
原因
-
AND 依赖前置条件为真
-
OR 更容易绕过逻辑限制
or if(1=1,sleep(5),0)
👉 实战中 OR 成功率更高
六、三步走核心思想(非常重要)
SQL 注入的本质,不在"函数",而在 改变执行逻辑并得到结果
三步走模型
1️⃣ 输入点在哪里?
- GET / POST / Cookie
- 进入 SQL 的哪一部分(WHERE / VALUES)
2️⃣ 我能改变什么逻辑?
- 条件判断
- 执行顺序
- 是否报错
- 是否延迟
3️⃣ 我如何判断结果?
- 页面变化(布尔)
- 时间变化(延时)
- 错误回显(报错)
七、CMS 实战案例分析
1️⃣ 熊海 CMS ------ INSERT 报错注入
关键代码
die(mysql_error());
注入点
- INSERT 语句
- 字符型参数
错误 payload(课程中出现,但逻辑上不严谨)
' and updatexml(...) and '
⚠ 注意:
- INSERT 中
AND没有逻辑语义 - INSERT 注入必须让函数成为"值表达式"
正确认知
- INSERT 注入 ≠ WHERE 注入
- 必须考虑:
- 字符型 / 数字型
- 值数量是否匹配
2️⃣ KKCMS ------ DELETE 时间盲注
注入点
DELETE FROM table WHERE id=$id
测试方式
and if(1=1,sleep(5),0)
or if(1=1,sleep(5),0)
时间现象
- sleep(1) → 延迟约 3s
- sleep(3) → 延迟约 9s
👉 无需精确,只要与正常请求有明显差异即可
3️⃣ 单引号被转义的绕过(重点)
问题
addslashes($_GET['id'])
解决方案
-
不使用字符串比较
-
使用
ord()+ 数值判断or if(ord(left(database(),1))=107,sleep(2),0)
八、DELETE / INSERT 注入的经验结论
| 操作 | 布尔 | 报错 | 延时 |
|---|---|---|---|
| SELECT | ✅ | ✅ | ✅ |
| INSERT | ❌(通常) | ✅ | ✅ |
| DELETE | ❌ | ❌ | ✅ |
| UPDATE | ❌ | 视情况 | ✅ |
九、最终总结(可背)
盲注不是"看不到数据",而是"通过逻辑变化间接获取数据"。
INSERT / DELETE 等操作不回显数据时,应优先考虑时间盲注;
若存在错误回显,则报错盲注效率最高。
SQL 注入与盲注 ------ 思路导向型笔记
一、第一性原则:SQL 注入不是"技巧",而是"控制执行逻辑"
任何 SQL 注入,本质都只干一件事:
让用户输入,参与并改变了数据库原本的执行逻辑
所以做题或实战时,不要先想:
- 用什么函数
- 用什么 payload
而要先问 三个问题:
- 这个功能在"正常情况下"是干嘛的?
- 我的输入进到了 SQL 的哪个位置?
- 我能不能让执行逻辑"发生可观察的变化"?
二、从功能反推注入类型(而不是反过来)
1️⃣ 看到功能,先不要想"注入"
先在脑子里自动翻译为 SQL 行为:
| 页面功能 | 后端大概率行为 |
|---|---|
| 查看新闻 | SELECT |
| 新增评论 / 用户 | INSERT |
| 删除数据 | DELETE |
| 修改内容 | UPDATE |
结论:
SQL 注入一定是"依附功能存在的",而不是独立存在的。
三、第二个关键判断:页面是否回显"数据库数据"
这是是否进入盲注分支的分水岭。
情况 A:页面直接显示数据
- 能看到字段值
- 能看到多行数据
👉 优先:普通注入 / 联合查询
情况 B:页面只显示"成功 / 失败"
- 新增成功
- 删除成功
- 操作失败
👉 直接进入:盲注思路
四、盲注不是一种,而是三条"判断路径"
盲注的核心不是函数,而是:
我靠什么"现象"来判断真假?
路径一:页面是否因"条件真假"而不同?(布尔盲注)
思路判断
- 条件为真时:
- 页面有内容
- 页面跳转
- 条件为假时:
- 页面空白
- 提示不同
👉 只要能区分,就能布尔
本质
利用 SQL 条件,控制"是否满足业务逻辑"
你判断的不是数据库值,而是:
- 逻辑有没有被满足
路径二:数据库错误是否会"被用户看到"?(报错盲注)
思路判断
-
页面是否出现:
- SQL 语法错误
- 数据库错误信息
-
后端是否存在:
die(mysql_error());
👉 能看到数据库错误 = 报错盲注优先
本质
把"我想要的数据",塞进数据库报错信息里
不是"制造错误",而是:
- 控制错误内容
路径三:什么都看不到?那就看"时间"(时间盲注)
思路判断
- 页面无回显
- 无报错
- 但请求耗时明显变化
👉 时间盲注是最后、也是最通用的方案
本质
用时间,代替页面内容,作为"结果载体"
你关心的不是 sleep,而是:
- 条件是否被执行
五、一个极其重要但容易忽略的问题:你的输入"进到哪了"?
这是你在 INSERT 报错那里卡住的根本原因。
不是所有注入点都一样
| 输入位置 | 可用逻辑 |
|---|---|
| WHERE | AND / OR |
| VALUES | 表达式本身 |
| SET | 表达式 |
| LIMIT | 数值运算 |
错误示例(思路错):
INSERT ... VALUES ('payload and condition')
正确思路:
INSERT 中,你不是"判断条件",
而是"构造一个会被执行的值"
六、INSERT / DELETE / UPDATE 的思路差异
INSERT
- 不关心"真假"
- 关心:
- 是否执行成功
- 是否报错
- 是否延迟
👉 布尔通常没意义
DELETE / UPDATE
- WHERE 存在
- 但删除成功 ≠ 有回显差异
👉 时间盲注成功率最高
七、为什么实战中经常"OR 比 AND 好用"
不是语法问题,是逻辑问题。
AND 的隐含前提
前面的条件必须成立
OR 的优势
只要我为真,整个逻辑就为真
👉 绕过限制更容易
八、单引号被过滤时,你该怎么想?
不要马上想:
- 绕过单引号
- 双写
- 编码
而是问:
我真的"必须用字符串吗"?
如果不需要:
- 用 ord()
- 用数值比较
- 用时间判断
思路转变是关键,不是技巧本身
九、你在实战中真正应该记住的"流程"
每个注入点,都走一遍这个流程:
- 这是哪种功能?
- 是否有数据回显?
- 是否有错误回显?
- 是否可以观察时间?
- 我的输入在 SQL 的哪一部分?
- 我能改变的是"条件"还是"值"?
当这 6 个问题想清楚了,payload 自然就出来了。
十、一句"总纲级总结"
SQL 注入不是背 payload,而是判断:
你能控制什么逻辑,用什么现象,来确认控制成功。