HTTP请求走私
翻译
原文:https://portswigger.net/web-security/request-smuggling
- name: 翻译
desc: 原文:https://portswigger.net/web-security/request-smuggling
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# 0HTTP请求走私
在本节中,我们将介绍 HTTP 请求走私攻击,并描述常见的请求走私漏洞是如何产生的。
实验室
如果你已经熟悉 HTTP 请求走私背后的基本概念,并且只想在一些实际的、易受攻击的目标上练习和利用它们,那么你可以从下面的链接访问本主题中的所有实验室。
# 1什么是HTTP请求走私?
HTTP 请求走私是一种技术,当网站从一个或多个用户处接收 HTTP 请求序列时,可用于干扰网站对请求的处理方式。请求走私漏洞通常很严重,允许攻击者绕过安全控制、获得对敏感数据的未授权访问等,并直接危及其他应用程序用户。
请求走私主要与 HTTP/1 请求相关联。但是,根据其后端架构的不同,支持 HTTP/2 的网站也可能受到攻击。
PortSwigger Research
HTTP 请求走私于 2005 年首次被记录,然后因 PortSwigger 对该主题的广泛研究而得到重新普及。有关详细信息,请查看以下白皮书:
# 2HTTP请求走私攻击会导致什么?
当今的 Web 应用程序,经常在用户和最终的应用程序逻辑之间使用 HTTP 服务器链。用户将请求发送到前端服务器(有时称为负载均衡器 或 反向代理),该前端服务器将请求转发到一个或多个后端服务器。这种类型的架构,在现代基于云的应用程序中越来越普遍,在某些情况下是不可避免的。
通常,当前端服务器将 HTTP 请求转发到后端服务器时,它会通过同一个后端网络连接来发送多个请求,因为这样效率更高,性能更好。实现该协议非常简单;HTTP 请求一个接一个地发送,接收端服务器必须确定一个请求的结束位置,以及下一个请求的开始位置:
在这种情况下,前端和后端系统必须就请求的边界达成一致,这一点至关重要。否则,攻击者可能会发送一个模糊的请求,前端和后端系统 会以不同的方式解释该请求:
在这里,攻击者使得前端请求的一部分,被后端服务器解释为下一个请求的开始。其被有效地放置到下一个请求之前,因此可能会干扰应用程序处理该请求的方式。这是一种请求走私攻击,可能会造成毁灭性的后果。
# 3HTTP请求走私漏洞是如何产生的?
大多数 HTTP 请求走私漏洞的出现,是因为 HTTP/1 规范提供了两种不同的方法来指定请求的结束位置:Content-Length
标头和Transfer-Encoding
标头。
Content-Length
标头很容易理解:它指定消息正文的长度(以字节为单位)。例如:
POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
q=smuggling
2
3
4
5
6
Transfer-Encoding
标头可用于指定 消息正文 所使用的分块编码。这意味着,消息正文包含一个或多个数据块。每个区块由特定的区块大小(以字节为单位,以十六进制表示)、换行符 和 区块内容组成。当遇到大小为零的区块时,消息将会终止。例如:
POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
b
q=smuggling
0
2
3
4
5
6
7
8
笔记
许多安全测试人员不知道分块编码可以在 HTTP 请求中使用,有两个原因:
- Burp Suite 会自动解压缩分块编码,使消息更易于查看和编辑。
- 浏览器通常不会在请求中使用分块编码,一般只可能在服务器响应中看到。
由于 HTTP/1 规范提供了两种不同的方法来指定 HTTP 消息的长度,因此,单个请求可以同时使用这两种方法,从而使它们相互冲突。该规范试图防止出现这个问题,通过声明 - 如果同时存在Content-Length
和Transfer-Encoding
标头,则应忽略Content-Length
标头。当只有一台服务器在运行时,这足以避免差异,但当两个或多个服务器链接在一起时,就不能行了。在这种情况下,出现问题的原因有两个:
- 某些服务器不支持请求中的
Transfer-Encoding
标头。 - 如果以某种方式,对标头进行模糊处理,则一些支持
Transfer-Encoding
标头的服务器可能会被诱导,从而变为不处理该标头。
如果前端和后端服务器对Transfer-Encoding
标头(可能是经过混淆的)存在不同的行为,则它们可能会在连续请求的边界上产生分歧,从而导致请求走私漏洞。
笔记
本质上,端到端使用 HTTP/2 的网站不受请求走私攻击的影响。由于 HTTP/2 规范引入了一种单一的、健壮的机制来指定请求的长度,因此攻击者无法引入所需的模糊性。
然而,许多网站都有一个 HTTP/2 的前端服务器,但将其部署在仅支持 HTTP/1 的后端基础设施之前。这意味着,对于接收到的请求,前端必须有效地将其转换为 HTTP/1。这个过程被称为 HTTP 降级。有关详细信息,请参阅高级请求走私 (opens new window)。
# 4如何实现HTTP请求走私攻击
经典的请求走私攻击,涉及将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” 部分执行此操作。
# 4.1CL.TE漏洞
在这里,前端服务器使用Content-Length
标头,后端服务器使用Transfer-Encoding
标头。我们可以执行一个简单的 HTTP 请求走私攻击,如下所示:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
前端服务器处理Content-Length
标头,并确定请求正文的长度为 13 个字节,直到SMUGGLED
的末尾。此请求将被转发至后端服务器。
后端服务器处理Transfer-Encoding
标头,因此将消息正文视为使用分块编码。它处理第一个块,该块的长度为零,因此被视为终止请求。后面的字节SMUGGLED
未被处理,后端服务器会将这些字节,视为下一个请求序列的开始。
- name: 实验室-从业者
desc: HTTP请求走私-基本CL.TE漏洞 >>
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/lab-basic-cl-te
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 4.2TE.CL漏洞
在这里,前端服务器使用Transfer-Encoding
标头,后端服务器使用Content-Length
标头。我们可以执行一个简单的 HTTP 请求走私攻击,如下所示:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
笔记
想要通过 Burp Repeater 发送此请求,你首先需要转到 Repeater 菜单并确保未勾选 “Update Content-Length” 选项。
你还需要在最后一个0
的后面包含序列\r\n\r\n
。
前端服务器处理Transfer-Encoding
标头,因此将消息正文视为使用分块编码。它处理第一个块,该块的长度为 8 个字节,直到SMUGGLED
下一行的开始。它处理第二个块,该块的长度为零,因此被视为终止请求。此请求将被转发至后端服务器。
后端服务器处理Content-Length
标头,并确定请求正文的长度为 3 个字节,直到8
下一行的开始。以SMUGGLED
开头的后续字节未被处理,后端服务器会将这些字节,视为下一个请求序列的开始。
- name: 实验室-从业者
desc: HTTP请求走私-基本TE.CL漏洞 >>
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/lab-basic-te-cl
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 4.3TE.TE行为:混淆TE标头
在这里,前端和后端服务器都支持Transfer-Encoding
标头,但可以通过某种方式,对标头进行模糊处理(混淆),来诱导其中一台服务器不处理它
混淆Transfer-Encoding
标头的方法可能有无数种。例如:
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这些技术中的每一种,都涉及到 HTTP 规范的微妙背离。实现协议规范的实际代码,很少会以绝对的精确度来遵守它,并且不同的实现之间,通常会容忍与规范不同的变化。要发现 TE.TE 漏洞,必须找到Transfer-Encoding
标头的某些变体,以便只有一台前端 或 后端服务器处理它,而另一台服务器忽略它。
在诱导服务器不处理混淆过的Transfer-Encoding
标头之后,判断其是前端服务器还是后端服务器,然后,攻击的其余部分将采用与 CL.TE 或 TE.CL 漏洞相同的形式。
- name: 实验室-从业者
desc: HTTP请求走私-混淆TE标头 >>
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/lab-obfuscating-te-header
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 5如何识别HTTP请求走私漏洞
请查看以下部分,获取有关于如何自行识别 HTTP 请求走私漏洞的一些提示。我们还提供了一些交互式LABS,你可以在实践中了解其工作原理。
# 6如何利用HTTP请求走私漏洞
现在,你已经熟悉了基本概念,让我们来看看如何利用 HTTP 请求走私来构建许多高严重性攻击。像往常一样,有很多交互式的LABS,你可以尝试攻击逼真的目标。
# 7高级HTTP请求走私
如果你已经完成了请求走私实验室的其余部分,那么你就可以学习一些更高级的技术了。我们根据 PortSwigger 研究人员发现的真实漏洞,创建了许多交互式LABS。你甚至有机会尝试 Burp 的基于 HTTP/2 的测试功能。
# 8浏览器驱动的请求走私
到目前为止,你所学到的请求走私技术,都依赖于使用专用的黑客工具(如 Burp Repeater)来发送故意格式错误的请求。事实上,可以使用完全兼容浏览器的请求,来执行相同的攻击,这些请求使用完全正常的Content-Length
标头来使两个服务器不同步。
这甚至使你能够启动这些攻击的客户端变体,这些变体会 诱使受害者的浏览器 毒害自身与易受攻击网站的连接。这不仅会使 单服务器站点 暴露于请求走私式攻击,甚至还使你能够攻击无法直接访问的站点。查看学习材料和LABS以了解如何操作。
# 9如何防范HTTP请求走私漏洞
当前端服务器和后端服务器,使用不同的机制来确定请求之间的边界时,就会出现 HTTP 请求走私漏洞。这可能是由于 HTTP/1 服务器使用了Content-Length
标头或是分块传输编码,在确定每个请求的结束位置时存在差异。在 HTTP/2 环境中,常见的为后端进行 HTTP/2 请求降级也充满了问题,并且会诞生或简化许多其他攻击。
为了防范 HTTP 请求走私漏洞,我们建议采取以下高级措施:
- 端到端使用 HTTP/2,并尽可能禁用 HTTP 降级。HTTP/2 使用可靠的机制来确定请求的长度,并且在实现端到端场景时,本质上可以防止请求走私。如果无法避免 HTTP 降级,请根据 HTTP/1.1 规范对重写后的请求进行验证。例如拒绝这些请求:标头中包含换行符、标头名称中包含冒号、以及在请求方法中包含空格。
- 在前端服务器对模糊请求进行规范化,并使后端服务器拒绝任何模糊请求,同时在此过程中关闭 TCP 连接。
- 永远不要假设请求没有正文。这是导致 CL.0 和客户端异步漏洞的根本原因。
- 在处理请求时,如果触发服务器级异常,则应默认丢弃连接。
- 如果通过代理来转发和路由流量,请确保尽可能启用上游 HTTP/2。
正如我们在学习材料中所展示的那样,禁用后端连接的复用 将有助于缓解某些类型的攻击,但这仍然不能避免请求隧道攻击。