一文了解Http Request-Smuggling

本文深入探讨了HTTP请求走私的概念,解释了由于HTTP规范的不同解析方式导致的安全漏洞。内容包括漏洞成因、五种攻击方式(CL不为0、CL-CL、CL-TE、TE-CL、TE-TE)及其利用场景,如绕过前端安全控制、捕获用户请求和执行Web缓存投毒。此外,还介绍了Gunicorn 20.0.4版本中的请求走私问题。提供了一系列实验链接以加深理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是 HTTP 请求走私?

不同服务器请求内容的标准不同,对同一段tcp内容,前后端服务器获取到的http请求内容会有一定差异,而这个差异就造成了HTTP请求走私。

漏洞成因

HTTP规范提供了两种不同的方法来指定请求的结束位置 :Content-Length标头和Transfer-
Encoding标头,若同一请求前端与后端所使用的规范不同就可能导致解析差异,从而造成请求走私。一般服务器有三种解析方式:

CL.TE:前端服务器使用Content-Length标头,而后端服务器使用Transfer-Encoding标头。
TE.CL:前端服务器使用Transfer-Encoding标头,而后端服务器使用Content-Length标头。
TE.TE:前端服务器和后端服务器都支持Transfer-Encoding标头,但是可以通过对标头进行某种方式的混淆来诱导其中一台服务器不对其进行处理。

这里的解析错误主要取决于HTTP1.1中的两个特性: keep-alive与pipeline

Keep-Alive :是在 HTTP 请求中增加一个特殊的请求头 Connection: Keep-Alive,告诉服务器,接收完这次 HTTP
请求后,不要关闭 TCP 链接,后面对相同目标服务器的 HTTP 请求,重用这一个 TCP 链接,这样只需要进行一次 TCP
握手的过程,可以减少服务器的开销,节约资源,还能加快访问速度。这个特性在 HTTP1.1 中是默认开启的。

Pipeline(http管线化)
:http管线化是一项实现了多个http请求但不需要等待响应就能够写进同一个socket的技术,仅有http1.1规范支持http管线化。在这里,客户端可以像
流水线
一样发送自己的HTTP请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端。

正常HTTP请求:

wKg0C2Lt3vGAWA5mAABSJE8j9I266.png

若前置服务器和后端服务器在 HTTP 请求的边界划分上未达成一致:

wKg0C2Lt3wiASPgZAABXFatgrBs013.png
当我们向代理服务器发送一个比较模糊的 HTTP 请求时,由于两者服务器的实现方式不同,可能代理服务器认为这是一个 HTTP
请求,然后将其转发给了后端的源站服务器,但源站服务器经过解析处理后,只认为其中的一部分为正常请求,剩下的那一部分,就算是走私的请求,当该部分对正常用户的请求造成了影响之后,就实现了
HTTP 走私攻击。

HTTP 流水线

上边写到Pipeline(http管线)可以像流水线一样发送http请求,所以这里简单了解下HTTP流水线原理

行nc xxx.xxx.xxx.xxx 80,然后发送三个HTTP请求。

GET / HTTP/1.1
Host: localhost
GET / HTTP/1.1
Host: localhost
GET / HTTP/1.1
Host: localhost

在一个连接中发送3个HTTP请求,服务器会按序响应3个HTTP请求。可以使用这种办法来最小化请求之间的间隔时间。但由于手工录入可能较慢,可能无法实现我们的意图,所以也可以用命令来代替。

echo -ne "GET / HTTP/1.1\r\nHost: localhost\r\n\r\nGET / HTTP/1.1\r\nHost: localhost\r\n\r\nGET / HTTP/1.1\r\nHost: localhost\r\n\r\n" | nc xxx.xxx.xxx.xxx 80

这里就可以结合请求走私,执行一些我们想要执行的操作。

五种攻击方式

CL不为0

所有不携带请求体的HTTP请求都有可能受此影响。前端代理服务器允许GET请求携带请求体;后端服务器不允许GET请求携带请求体,它会直接忽略掉GET请求中的Content-
Length头,不进行处理。这就有可能导致请求走私。

代码实例:

GET / HTTP/1.1
Host: Sentiment.com
Content-Length: 44

GET / secret HTTP/1.1
Host: Sentiment.com

这里要提一下长度的计算规则:

Content-Length 需要将请求主体中的 \r\n 所占的 2 字节计算在内,而块长度要忽略块内容末尾表示终止的 \r\n;

请求头与请求主体之间有一个空行,是规范要求的结构,并不计入 Content-Length。

所以这里的44=21+19+2*2(这两行后边的换行,即:(\r\n)

wKg0C2Lt32GALABlAAAcR0oZdPQ276.png

攻击流程

前端:收到该请求,读取Content-Length,判断这是一个完整的请求。 后端:因为它不对Content-
Length进行处理,由于Pipeline的存在,后端服务器就认为这是收到了两个请求,分别是:

第一个:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值