基于暂停的异步攻击
翻译
原文:https://portswigger.net/web-security/request-smuggling/browser/pause-based-desync
- name: 翻译
desc: 原文:https://portswigger.net/web-security/request-smuggling/browser/pause-based-desync
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# 1基于暂停的异步攻击
看似安全的网站可能包含隐藏的异步漏洞,只有在你中途暂停请求时才会暴露出来。
服务器通常设置了读取超时。如果服务器在一定时间内,没有收到更多的数据,服务器会将请求视为完成并发出响应,而不管服务器被告知预期有多少字节。当服务器请求超时,但连接仍然保持开放状态以供复用时,可能会发生基于暂停的异步漏洞。如果条件合适,这种行为可以为服务端和客户端异步攻击提供一个替代向量。
PortSwigger Research
本节中的材料和实验基于 PortSwigger Research 的《浏览器驱动的异步攻击-HTTP请求走私的新前沿》 (opens new window)。
# 2基于暂停的服务端异步
你可以使用基于暂停的技术,来引发类似 CL.0 (opens new window) 的行为,从而允许你构建服务端请求走私漏洞。
这取决于以下条件:
- 前端服务器必须立即将 请求的每个字节 转发到后端,而不是等待完整请求接收完毕。
- 前端服务器不能(或可以诱使其不要)在后端服务器发出响应之前超时请求。
- 后端服务器必须使连接保持开放状态,以便在读取超时后复用。
为了演示这种技术的工作原理,让我们通过一个示例来演练。以下是标准的 CL.0 请求走私 (opens new window)探测:
POST /example HTTP/1.1
Host: vulnerable-website.com
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
GET /hopefully404 HTTP/1.1
Foo: x
2
3
4
5
6
7
8
考虑一下,如果我们将标头发送到易受攻击的网站,但在发送正文之前暂停会发生什么。
- 前端将标头转发到后端,然后继续等待
Content-Length
标头承诺的剩余字节。 - 一段时间后,后端超时并发送响应,即使它只收到了请求的一部分。此时,前端可能不会读取此响应,而是直接将其转发给我们。
- 我们发送最后的正文,在本例中,它包含一个基本的请求走私前缀。
- 前端服务器将其视为初始请求的延续,并通过相同的连接,将其转发到后端。
- 后端服务器已经响应了初始请求,因此假定这些字节是另一个请求的开始。
至此,我们已经有效地实现了 CL.0 异步,用请求前缀毒害了前端 / 后端连接。
我们发现,当服务器自己生成响应,而不是将请求传递给应用程序时,它们更容易受到攻击。
PortSwigger Research
我们的研究团队在广泛使用的 Apache HTTP Server 上发现了这个漏洞,该服务器在执行从/example
到/example/
的服务器级重定向时,表现出这种行为。我们报告了此问题,该问题已在版本 2.4.53 中得到修复,因此,如果你尚未更新,请务必及时更新。有关更多详细信息,请参阅《浏览器驱动的异步攻击-HTTP请求走私的新前沿》 (opens new window)。
# 2.1测试基于暂停的CL.0漏洞
可以使用 Burp Repeater 来测试基于暂停的 CL.0 漏洞,但前提是,前端服务器在生成后端的超时响应时,会将其转发给你,但情况并非总是如此。我们建议使用 Turbo Intruder (opens new window) 扩展,因为它允许你暂停请求、暂停后继续,无论你是否收到响应。
- 在 Burp Repeater 中,创建一个 CL.0 请求走私探测器,就像我们在上面的例子中使用的一样,然后将其发送到 Turbo Intruder。
POST /example HTTP/1.1
Host: vulnerable-website.com
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
GET /hopefully404 HTTP/1.1
Foo: x
2
3
4
5
6
7
8
- 在 Turbo Intruder 的 Python 编辑器面板中,调整请求引擎配置,以设置以下选项:
concurrentConnections=1
requestsPerConnection=100
pipeline=False
2
3
- 将请求添加到队列,并将以下参数添加到
queue()
接口:
pauseMarker
- 你希望 Turbo Intruder 遇到哪些字符时暂停,提供一个字符串列表。pauseTime
- 暂停的持续时间(以毫秒为单位)。
例如,若要在标头结束后暂停 60 秒,请按如下方式将请求添加到队列:
engine.queue(target.req, pauseMarker=['\r\n\r\n'], pauseTime=60000)
- 正常对任意后续请求进行队列添加:
followUp = 'GET / HTTP/1.1\r\nHost: vulnerable-website.com\r\n\r\n'
engine.queue(followUp)
2
- 确保将所有响应都记录到结果列表中:
def handleResponse(req, interesting):
table.add(req)
2
首次发起攻击时,你不会在表格中看到任何结果。但是,在暂停指定的时间过后,你应该会看到两个结果。如果对第二个请求的响应,与你预期的走私前缀(在本例中为 404)相匹配,则强烈表明异步已经成功。
- name: 实验室-专家
desc: 基于暂停的服务端请求走私 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/request-smuggling/browser/pause-based-desync/lab-server-side-pause-based-request-smuggling
bgColor: '#001350'
textColor: '#d112fe'
2
3
4
5
6
笔记
你可以使用pauseBefore
参数来指定偏移量,而不是使用pauseMarker
匹配字符串进行暂停。例如,可以通过指定与Content-Length
(pauseBefore=-34
)相反的偏移量,在正文之前暂停。
# 3基于暂停的客户端异步
理论上,可以执行基于暂停的 CL.0 客户端异步变体。但不幸的是,我们还没有找到一种可靠的方法,来使浏览器中途暂停请求。但是,有一种可能的解决方法 - 主动 MITM 攻击。
TLS 提供的加密可能会阻止 MITM 在传输中读取流量,但你可以延迟从浏览器到 Web 服务器的 TCP 数据包。通过简单地延迟最后一个数据包,直到 Web 服务器发出响应,你可以使浏览器连接变成异步。
这种攻击的流程,类似于其他任何客户端异步攻击。用户访问恶意网站,这会导致其浏览器向目标站点发出一系列跨域请求。在这种情况下,你需要故意填充第一个请求,以便操作系统将其拆分为多个 TCP 数据包。当你控制填充时,你可以填充请求,直到最后一个数据包具有不同的大小,以便你可以确定要延迟哪个数据包。
有关该攻击的实际示例,请参阅《浏览器驱动的异步攻击-HTTP请求走私的新前沿》 (opens new window)。
# 4如何防范基于暂停的异步漏洞
可用于防范 基于暂停的异步漏洞 和其他异步攻击的一些高级措施,请参阅如何防范 HTTP 请求走私漏洞 (opens new window)。