在2019年hackone的赏金中,HTTP请求走私漏洞大约占到了四分之一。这是一个2015年兴起的漏洞。在2019年又一次被重新重视起来。可以说是文艺复兴吧。在2019年的BlackHat USA 2019上,PortSwigger的James Kettle在他的议题——HTTP Desync Attacks: Smashing into the Cell Next Door中针对当前的网络环境,展示了使用分块编码来进行攻击的攻击方式,扩展了攻击面,并且提出了完整的一套检测利用流程。今天揭开HTTP请求走私漏洞的神秘面纱,本期文章让大家一起认识HTTP请求走私的原理及危害。

一、什么是HTTP?

http是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII码形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使得开发和部署是那么的直截了当。

中文名外文名工作层基 础适用浏览器作 用
超文本传输协议HTTP应用层架构在TCP协议上Firefox、Google chrome等规定WWW服务器与浏览器之间信息传递规范

二、什么是应用层?

OSI ( Open System Interconnect ),即开放式系统互联。 一般都叫 OSI 参考模型,是 ISO (国际标准化组织)组织在 1985 年研究的网络互联模型。该体系结构标准定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层和应用层),即 ISO 开放系统互连参考模型。在这一框架下进一步详细规定了每一层的功能,以实现开放系统环境中的互连性、互操作性和应用的可移植性。

下边是七层协议以及简单的用途:
物理层(01比特流的转换)
数据链路层(物理通路的发送和数据包的划分,附加Mac地址到数据包)
网络层(根据目的地址选择发送数据包路径–路由选择)
传输层(链接建立和断开,保证传输的可靠–重发机制)
会话层(发送的顺序和方法)
表示层(编码的格式)
应用层(具体的应用发送内容)

第 7 层应用层: OSI 中的最高层。 为特定类型的网络应用提供了访问 OSI 环境的手段。应用层确定进程之间通信的性质,以满足用户的需要。应用层不仅要提供应用进程所需要的信息交换和远程操作,而且还要作为应用进程的用户代理,来完成一些为进行信息交换所必需的功能。它包括:文件传送访问和管理 FTAM 、虚拟终端 VT 、事务处理 TP 、远程数据库访问 RDA 、制造报文规范 MMS 、目录服务 DS 等协议;应用层能与应用程序界面沟通,以达到展示给用户的目的。 在此常见的协议有 :HTTP , HTTPS , FTP , TELNET , SSH , SMTP , POP3 等

三、漏洞时间线

最早在2005年,由Chaim Linhart,Amit Klein,Ronen Heled和Steve Orrin共同完成了一篇关于HTTP Request Smuggling这一攻击方式的报告。通过对整个RFC文档的分析以及丰富的实例,证明了这一攻击方式的危害性。

在2016年的DEFCON 24 上,@regilero在他的议题——Hiding Wookiees in HTTP中对前面报告中的攻击方式进行了丰富和扩充。

在2019年的BlackHat USA 2019上,PortSwigger的James Kettle在他的议题——HTTP Desync Attacks: Smashing into the Cell Next Door中针对当前的网络环境,展示了使用分块编码来进行攻击的攻击方式,扩展了攻击面,并且提出了完整的一套检测利用流程。

四、漏洞原理

HTTP请求走私这一攻击方式很特殊,它不像其他的Web攻击方式那样比较直观,它更多的是在复杂网络环境下,不同的服务器对RFC标准实现的方式不同,程度不同。这样一来,对同一个HTTP请求,不同的服务器可能会产生不同的处理结果,这样就产生了安全风险。

HTTP 1.1协议相对于1.0主要引入了两个新的特性: Keep-Alive和pipline

1、Keep-Alive特性具体是指在HTTP请求头中,在建立TCP连接传输数据的时候传输完保持会话等待下一次传输数据。添加一个参数

Connection: Keep-Alive

告诉服务器在收到这个请求后不要关闭连接,后面再次发起请求时,继续使用这个TCP连接。
2、pipline特性是指在一次TCP连接中,可以连续不断地发送多个HTTP请求,而不必等待服务器响应。服务器会根据顺序进行处理。

有了这两个特性之后,HTTP 1.1相对于 HTTP 1.0来说,传输效率更高,如今HTTP 1.1也应用最为广泛。

在RFC 2616中规定,一个完整的数据包中需要在请求头部分包含”Content-Length”或者”Transfer-Encoding”来对数据包的长度进行说明。
1、Content-Length: 指明数据包的内容长度,一个字符长度为1,回车(rn)长度为2。如:
http1.png
这个数据包的请求长度为10:
2、Transfer-Encoding: 当值为chunked时,服务器在读取到
http2.png

0\r\n\r\n

后就会认为该请求已经结束。

而之后的内容会存在于服务器的缓存中,和下一个请求一起发送给服务器。

HTTP请求走私漏洞的核心就在于前端和后端对于请求的长度判断不一而引起的。

如当前端使用Content-Length来判断,而后端使用Transfer-Encoding:chunked来判断时,我们构造一个请求如:
http3.png
前端认为请求长度为6,会将所有内容转发给后端,而后端读到”0rnrn”后就认为请求已经结束,因此最后一个”G”就会留到缓存服务器中,被拼接到下一个请求的开始,如
http4.png
这样当下一个正常用户发起请求时,就会返回错误,因为服务器并不认得”GPOST”是什么请求方式。

这就是一个简单的HTTP请求走私攻击的例子。

上面这个例子中,前端使用Content-Length判断,后端使用Transfer-Encoding:chunked判断,因此属于CL-TE类型,与之对应的还有TE-CL、TE-TE。

五、漏洞实战

利用工具:Burpsuite

需要在Repeater中关闭更新Content-Length
1.png
以CL-TE为例 :

正常访问:
2.png
开启抓包,将请求改为POST方式

构造请求
3.png
放包。当下一个用户访问这个页面时
4.png

六、进阶操作

经过我深入学习会给大家带来进阶操作:

  1. 绕过前端服务器的安全控制(可以直接绕过WAF)
  2. 获取前端服务器重写请求字段
  3. 获取其他用户的请求(简单讲获取下一个访问用户的请求)
  4. 利用反射型XSS
  5. 进行缓存投毒

七、如何防御

  • 禁用代理服务器与后端服务器之间的TCP连接重用。
  • 使用HTTP/2协议。
  • 前后端使用相同的服务器。

以上的措施有的不能从根本上解决问题,而且有着很多不足,就比如禁用代理服务器和后端服务器之间的TCP连接重用,会增大后端服务器的压力。使用HTTP/2在现在的网络条件下根本无法推广使用,哪怕支持HTTP/2协议的服务器也会兼容HTTP/1.1。从本质上来说,HTTP请求走私出现的原因并不是协议设计的问题,而是不同服务器实现的问题,个人认为最好的解决方案就是严格的实现RFC7230-7235中所规定的的标准,但这也是最难做到的。

Last modification:June 16th, 2020 at 07:46 pm