HTTP请求走私笔记
个人总结
参考:https://portswigger.net/web-security/request-smuggling
- name: 个人总结
desc: 参考:https://portswigger.net/web-security/request-smuggling
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# HTTP请求走私笔记
# 1HTTP请求走私基本知识
# 1、HTTP请求走私是什么?
答案
HTTP 请求走私是一种技术,当网站从一个或多个用户处接收 HTTP 请求序列时,可用于干扰网站对请求的处理方式。
# 2、请求走私与HTTP协议的哪些版本有关?
答案
请求走私主要与 HTTP/1 请求相关联。
但是,根据服务器后端架构的不同,支持 HTTP/2 的网站也可能受到攻击。
# 3、HTTP请求走私一般会导致什么后果?
答案
请求走私漏洞通常很严重,允许攻击者干扰网站对请求的处理方式,并绕过安全控制、获得对敏感数据的未授权访问等,并直接危及其他应用程序用户。
# 4、HTTP/1中的请求走私漏洞是如何产生的?
答案
HTTP/1 规范提供了两种不同的方法来指定请求的结束位置:Content-Length
标头和Transfer-Encoding
标头。
单个请求可以同时使用这两种方法,从而使它们相互冲突。当只有一台服务器在运行时,协议规范会避免产生冲突,但当两个或多个服务器链接在一起时(服务器链),就不太能够避免了。在这种情况下,出现问题的原因有两个:
- 某些服务器不支持请求中的
Transfer-Encoding
标头。 - 如果以某种方式,对标头进行模糊处理,则一些支持
Transfer-Encoding
标头的服务器可能会被诱导,从而变为不处理该标头。
如果前端和后端服务器对Transfer-Encoding
标头(可能是经过混淆的)存在不同的行为,则它们可能会在连续请求的边界上产生分歧,从而导致请求走私漏洞。
# 5、HTTP/1如何实现基本的请求走私?有哪三种攻击类型?
答案
经典的请求走私攻击,涉及将Content-Length
标头和Transfer-Encoding
标头放入单个 HTTP/1 请求中,并操纵这些标头,从而使前端和后端服务器以不同的方式处理请求。完成此操作的确切方式,取决于两台服务器的行为:
- CL.TE:前端服务器使用
Content-Length
标头,后端服务器使用Transfer-Encoding
标头。 - TE.CL:前端服务器使用
Transfer-Encoding
标头,后端服务器使用Content-Length
标头。 - TE.TE:前端和后端服务器都支持
Transfer-Encoding
标头,但可以通过某种方式,对标头进行模糊处理,来诱导其中一台服务器不处理它。
笔记
这些技术只能使用 HTTP/1 请求。默认情况下,浏览器和其他客户端(包括 Burp)使用 HTTP/2 与服务器进行通信,这些服务器在 TLS 握手期间显式通告对协议的支持。
因此,在测试支持 HTTP/2 的站点时,你需要在 Burp Repeater 中手动切换协议。你可以在 “Inspector” 面板的 “Request attributes” 部分执行此操作。
:::
# 6、Transfer-Encoding
标头指定的每个区块大小是由几进制表示的?
答案
十六进制,以下是一个 TE.CL 攻击示例(2b
在十进制中表示43
):
POST / HTTP/1.1
Host: ...
Transfer-Encoding: chunked
Content-Length: 4
2b
GPOST / HTTP/1.1
Content-Length: 100
x=
0
2
3
4
5
6
7
8
9
10
11
12
13
# 2查找HTTP请求走私漏洞
# 1、为什么要用其他技术来识别HTTP请求走私漏洞?
答案
通常,检测请求走私漏洞的明显方法是发出一个模糊的请求,然后发出一个正常的 “受害者” 请求,并观察后一个请求是否得到意外响应。
但是,这种检测方法极易受到干扰。如果同一时间内,有另一个用户也发送了请求,并正好命中了有害的响应,则我们将无法发现漏洞。
这意味着,在流量较大的实时网站上很难证明请求走私的存在。即使在一个没有其他流量的网站上,目标应用程序也可能会异常终止连接,造成假阴性的风险。
# 2、使用计时技术来查找CL.TE和TE.CL漏洞
答案
如果应用程序容易受到请求走私的 CL.TE 变体攻击,则发送如下请求通常会导致时间延迟:
- 由于前端服务器使用
Content-Length
标头,因此它只会转发此请求的一部分,省略X
。 - 后端服务器使用
Transfer-Encoding
标头,处理第一个区块,然后等待下一个区块到达。这将导致明显的时间延迟。
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4
1
A
X
如果应用程序容易受到请求走私的 TE.CL 变体攻击,则发送如下请求通常会导致时间延迟:
- 由于前端服务器使用
Transfer-Encoding
标头,因此它只会转发此请求的一部分,省略X
。 - 后端服务器使用
Content-Length
标头,期望消息正文中有更多内容,并等待剩余内容到达。这将导致明显的时间延迟。
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6
0
X
笔记
如果应用程序容易受到 CL.TE 变体攻击,则基于时间的 TE.CL 测试可能会中断其他应用程序用户。因此,为了隐秘且最大限度地减少干扰,你应该首先进行 CL.TE 测试,只有在测试不成功时才继续 TE.CL 测试。
:::
# 3、通过响应差异来确定CL.TE和TE.CL漏洞
答案
要确认 CL.TE 漏洞,你可以发送如下攻击请求:
- 前端服务器使用
Content-Length
标头,正常转发请求。 - 后端服务器使用
Transfer-Encoding
标头,第一个区块长度为0
,被视为终止请求。此请求的最后两行,将被视为下一个请求的一部分。然后,由于下一个请求包含无效的 URL,因此服务器将以状态码 404 进行响应,表明攻击请求确实干扰了它。
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
Foo: x
要确认 TE.CL 漏洞,你可以发送如下攻击请求:
- 前端服务器使用
Transfer-Encoding
标头,识别第一个区块长度为7c
(十六进制),正常处理数据。第二个区块长度为0
,被视为终止请求,正常转发请求。 - 后端服务器使用
Content-Length
标头,所指定的内容长度为4
,所以只读取了数据7c\r\n
(包括换行符,一共四个字节)。后端服务器会将GET /404
之后的所有内容,都视为下一个请求的一部分。然后,由于下一个请求包含无效的 URL,因此服务器将以状态码 404 进行响应,表明攻击请求确实干扰了它。
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
7c
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100
x=
0
# 3利用HTTP请求走私漏洞
# 1、HTTP请求走私漏洞有哪些利用方式?
答案
# 4高级HTTP请求走私(HTTP/2请求走私)
# 1、HTTP/2是一种XXX协议?
答案
HTTP/2 是一种二进制协议。以一种人类不可读的文本形式进行传输。
# 2、HTTP/2的消息长度
答案
HTTP/2 引入了一个单一的、健壮的机制来实现消息长度。
HTTP/2 消息其实是作为一系列单独的 “帧” 来通过网络发送的。每个帧的前面都有一个显式的长度字段,该字段告诉服务器要读入的确切字节数。因此,请求的长度是其帧长度的总和。
从理论上讲,这种机制意味着,只要网站端到端使用 HTTP/2,攻击者就没有机会引入请求走私所需的模糊性。然而,在野外,由于 HTTP/2 降级的广泛且危险性,情况往往并非如此。
# 3、HTTP/2降级是什么?
答案
使用 HTTP/1 语法重写 HTTP/2 请求,以生成等效 HTTP/1 请求的过程。
在与仅支持 HTTP/1 的后端服务器通信时,Web 服务器和反向代理经常这样做,以便向客户端提供 HTTP/2 支持。该机制是许多 HTTP/2 请求走私攻击的先决条件。
# 4、H2.CL漏洞如何实现?
答案
客户端与前端服务器使用 HTTP/2 进行通信
- 虽然 HTTP/2 自身有一套计算正文长度的机制,但攻击者依然可以在请求中添加
Content-Length: 0
标头。 - 前端服务器不会处理和使用
Content-Length: 0
标头,且未对其进行正确验证。
前端服务器与后端服务器使用 HTTP/1 进行通信
- 前端服务器使用 HTTP/1 对原有请求进行重写(HTTP/2降级),重写过后的请求包含
Content-Length: 0
标头。然后将新请求转发给后端服务器。 - 后端服务器会处理
Content-Length: 0
标头。由于指定了正文长度为0
字节,所以请求正文被有效滞留在后端服务器,并将其视为下一个请求的一部分。
# 5、H2.TE漏洞如何实现?
答案
与 H2.CL 漏洞类似,将标头和正文替换为 TE 漏洞的相应载荷即可。
# 6、响应队列投毒是什么?造成的后果?
答案
- 响应队列投毒是一种强大的请求走私攻击形式,它会导致前端服务器 将来自后端的响应 映射到错误的请求上。在实践中,这意味着同一个前端 / 后端连接的所有用户,都会持续地收到其他用户的响应。
- 后果:
- 攻击者只需发出任意后续请求,即可捕获其他用户的响应。这些响应可能包含敏感的个人或业务数据、会话令牌等,这实际上授予了 攻击者对受害者帐户的完全访问权限。
- 响应队列投毒还会造成重大的附加损害,这会破坏站点,因为任何其他用户的流量都是通过同一个 TCP 连接发送到后端的。当用户试图正常浏览网站时,用户将收到来自服务器的随机响应,这将阻碍大多数功能正常工作。
# 7、构造响应队列投毒的条件和步骤?
答案
要想成功执行响应队列投毒攻击,必须满足以下条件:
- 前端服务器和后端服务器之间的 TCP 连接重复用于多个请求 / 响应周期 (opens new window)。
- 攻击者能够成功地走私一个完整的独立请求,该请求从后端服务器接收其自身的不同响应。
- 该攻击不会导致任何一台服务器关闭 TCP 连接。服务器通常会在 收到无效请求时 才关闭传入连接,因为它们无法确定请求应该在哪里结束。
步骤:
# 8、响应队列投毒攻击需要通过HTTP/1还是HTTP/2实现?
答案
这种攻击既可以通过经典的 HTTP/1 请求走私、也可以通过利用 HTTP/2 降级来实现。
# 9、有哪些注入HTTP/2专用攻击向量的方法?
# 10、CRLF是如何实现请求走私的?
答案
利用 HTTP/2 和 HTTP/1 解析 CRLF 序列(\r\n
)时的差异:
- HTTP/2 的消息是基于二进制的,而非基于文本,所以字符
\r\n
对于 HTTP/2 来说没有任何特殊意义。 - 当它被重写为 HTTP/1 请求时(HTTP/2 降级),
\r\n
将再次被解释为标头分隔符。
# 11、CRLF是如何实现请求拆分的?
答案
在标头中注入 CRLF 序列即可。
- 这样即使是
GET
请求也能实现请求走私。 - 在
Content-length
得到充分验证 且 后端不支持分块编码的情况下,这非常有用。
(一般的请求走私是在请求正文中注入 CRLF 序列,通常需要用到POST
方法)
# 12、HTTP/2请求隧道攻击是如何实现的?
答案
经典请求走私攻击(会复用同一连接):
- 发送一个请求,其中包含正常请求 和 走私的请求。
- 正常请求立即得到处理,返回正常响应。走私的请求被滞留在后端服务器,被视为下一个请求的一部分。
请求隧道攻击(不会复用同一连接):
- 发送一个请求,其中包含正常请求 和 走私的请求。
- 两个请求都被立即处理,走私响应 被包含在 正常响应的正文中,混合为一个响应返回给攻击者。
# 13、盲请求隧道和HEAD复明请求隧道?
答案
请求隧道攻击会将两个响应混合在一起,一些前端服务器只会根据Content-Length
来读取指定的字节数,由于Content-Length
长度不够,所以前端只能够读取和返回第一个正常请求的响应,第二个隧道请求的响应会被省略。这会导致盲请求隧道漏洞,因为你无法看到第二个隧道请求的响应。
HEAD
请求方法是一种轻量级的GET
请求,HEAD
响应包含一样的响应标头,但不会返回响应正文。
- 在第一个正常请求里面使用
HEAD
方法,使其返回Content-Length
响应标头,但不返回响应正文 - 由于第一个正常响应没有正文,所以第二个隧道响应的正文就会填补这个空缺,使我们可以再次看到隧道请求的响应。
- 一般的请求隧道:正常响应标头 + 正常响应正文 + 隧道响应标头 + 隧道响应正文
- HEAD 复明请求隧道:正常响应标头 + 隧道响应标头 + 隧道响应正文
# 5浏览器驱动的请求走私
# 1、CL.0请求走私
答案
原理:
- 一些不接受
POST
请求的端点存在隐式假设 - 该端点接收的请求不会带有正文,从而忽略Content-Length
标头(相当于Content-Length: 0
)。如果后端服务器表现出这种行为,但前端仍然使用Content-Length
标头来确定请求的结束位置,则你可以利用这种差异进行 HTTP 请求走私。 - 如果无法找到以上端点,也可以对
Content-Length
标头进行一些混淆 (opens new window),使后端服务器忽略它,以实现相同的效果。
最佳端点:
- 触发服务器级重定向 和 静态文件请求的端点,是主要候选者。
利用 CL.0 漏洞:
- 和之前的漏洞一样,可以执行相同的服务端请求走私攻击。
# 2、客户端异步(CSD)攻击
答案
对比:
- 常规请求走私攻击:使 前端和后端服务器 之间的连接失去同步。
- 客户端异步(CSD)攻击:使受害者的 Web 浏览器与易受攻击网站的连接失去同步。
原理:
- 诱使 Web 服务器在不读取正文的情况下响应
POST
请求(类似 CL.0 请求走私)。随后,使浏览器复用同一连接,导致客户端异步漏洞。 - (Web 服务器不读取正文,正文数据有效滞留在服务器上,随后浏览器通过同一连接发送的请求,会和先前的滞留数据拼接在一起进行处理)
最佳端点:
- 触发服务器级重定向 和 静态文件请求的端点,是主要候选者。
需要用户交互:
- 攻击者需要在恶意域上构建 js 利用代码,诱使受害者访问该恶意页面。
利用 CSD 漏洞(客户端请求走私):
# 3、测试客户端异步(CSD)攻击的最佳流程
答案
由于需要依赖浏览器进行攻击,导致攻击的复杂性增加,因此在测试客户端异步漏洞时必须有条不紊。虽然有时很想跳过一些步骤,但我们建议采用以下工作流程。这可以分阶段来确认每个攻击元素的假设。
- 在 Burp 中探测潜在的异步向量。
- 在 Burp 中确认异步向量。
- 构建概念验证,以在浏览器中复现行为。
- 识别一个可利用的小工具。
- 在 Burp 中构建一个有效的漏洞利用。
- 在你的浏览器中复现该漏洞利用。
# 4、基于暂停的异步攻击
答案
分类:
- 基于暂停的服务端异步(可引发类似 CL.0 的行为)
- 基于暂停的客户端异步(至今为止暂未实现,因为无法使浏览器中途暂停发送请求)
基于暂停的服务器异步-利用条件:
- 前端服务器必须立即将 请求的每个字节 转发到后端,而不是等待完整请求接收完毕。
- 前端服务器不能(或可以诱使其不要)在后端服务器发出响应之前超时请求。
- 后端服务器必须使连接保持开放状态,以便在读取超时后复用。
# 5、基于暂停的服务器异步-原理
答案
将一个请求发送到易受攻击的网站,但在发送正文之前暂停发送请求:
- 前端将请求的标头部分转发到后端,然后继续等待
Content-Length
标头承诺的剩余字节。 - 一段时间之后,后端超时并发出响应,即使它只收到了请求的一部分。此时,前端可能不会读取此响应,而是直接将其转发给我们。
- 我们重启暂停的请求,发送最后的正文。
- 前端服务器将其视为初始请求的延续,并通过相同的连接,将其转发到后端。
- 由于后端服务器已经响应了初始请求,因此假定这些字节是另一个请求的开始。
# 6漏洞总结
# 1、HTTP请求走私分类
答案
按协议版本分类:
- HTTP/1 请求走私(两种长度计算机制,引起解析差异)
- HTTP/2 请求走私(因 HTTP/2 降级引起)
按端点分类:
- 服务端请求走私
- 客户端请求走私
# 2、各类HTTP请求走私产生的漏洞
# 3、HTTP请求走私的利用方式
答案
HTTP/1 请求走私-漏洞利用:
HTTP/2 请求走私-漏洞利用:
浏览器驱动的请求走私-漏洞利用:
- 经典的服务端请求走私利用方式(见 HTTP/1)
- 经典攻击的客户端变体
# 7防范HTTP请求走私漏洞
答案
漏洞成因:
- HTTP/1 服务器使用了
Content-Length
标头或是分块传输编码,在确定每个请求的结束位置时存在差异。 - 在 HTTP/2 环境中,常见的 HTTP/2 请求降级也充满了问题,并且会诞生或简化许多其他攻击。
为了防范 HTTP 请求走私漏洞,我们建议采取以下高级措施:
- 端到端使用 HTTP/2,并尽可能禁用 HTTP 降级。
- 如果无法避免 HTTP 降级,请根据 HTTP/1.1 规范对重写后的请求进行验证。例如拒绝这些请求:标头中包含换行符、标头名称中包含冒号、以及在请求方法中包含空格。
- 在前端服务器对模糊请求进行规范化,并使后端服务器拒绝任何模糊请求,同时在此过程中关闭 TCP 连接。
- 永远不要假设请求没有正文。这是导致 CL.0 和客户端异步漏洞的根本原因。
- 在处理请求时,如果触发服务器级异常,则应默认丢弃连接。
- 如果通过代理来转发和路由流量,请确保尽可能启用上游 HTTP/2。
另外,正如 PortSwigger 在学习材料中所展示的那样,禁用后端连接的复用 将有助于缓解某些类型的攻击,但这仍然不能避免请求隧道攻击(通过同一个连接发送多个请求)。