【技术向】HTTP/1与HTTP/2(H2C)走私攻击

发布者:星河Salaxy
发布于:2021-04-08 13:31

一.  HTTP请求走私攻击

HTTP(Hyper Text Transfer Protocol,超文本传输协议)是万维网服务器传输超文本至本地浏览器的传送协议。HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。


简单的网络环境中,我们直接通过浏览器访问服务器,但是由于很多静态资源需要在服务器提供,这种方式无疑是大大增加了web服务器的负荷。


在稍微复杂的网络环境中,为了提升用户的浏览速度,提高使用体验,减轻服务器的负担,很多网站都用上了CDN加速服务,即在源站的前加上一个具有缓存功能的反向代理服务器,用户可直接从代理服务器获取静态资源,而无需从源站所在服务器中获取。另一方面,这个反向代理可以隐藏web服务器的真实IP,所以很多中小型网站都采用类似方案。常见拓扑图如下:


图片



一般来说,反向代理服务器与后端的源站服务器之间,会重用TCP链接。这也很容易理解,用户的分布范围是十分广泛,建立连接的时间也是不确定的,这样TCP链接就很难重用,而代理服务器与后端的源站服务器的IP地址是相对固定,不同用户的请求通过代理服务器与源站服务器建立链接,这两者之间的TCP链接进行重用,也就顺理成章了。



HTTP走私原理


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


HTTP请求走私漏洞是因为前端的反向代理服务器和后端的Web服务器,对同一个请求的理解不一致造成的。因此,针对同一个HTTP请求,不同的服务器可能会产生不同的处理结果,这样就产生了安全风险。


图片


如上图,攻击者恶意构造一个用户请求。这个请求被前端服务器理解为两个完整的请求,而后端服务器理解为一个请求和一个不完整的请求,于是后端服务器会等待正常用户的访问请求,只有将“不完整”请求与正常请求拼接后才对其响应。


HTTP走私演示


根据破坏请求的方式不同,一般将HTTP走私分为几种不同的情形(CL:Content-Length, TE:Transfer-Encoding):


Ø  CL!=0

Ø  CL-CL

Ø  CL-TE

Ø  TE-CL

Ø  TE-TE


下面演示CL-TE的攻击方式。所谓CL-TE,就是当收到存在两个请求头的请求包时,前端代理服务器只处理Content-Length请求头,而后端服务器会遵守RFC2616的规定,忽略掉Content-Length,处理Transfer-Encoding请求头。


Lab 地址:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te


连续发送几次请求就可以获得该响应:


图片


由于前端服务器处理Content-Length,所以这个请求对于它来说是一个完整的请求,请求体的长度为6,如下:


0\r\n

\r\n

G



当请求包经过代理服务器转发给后端服务器时,后端服务器处理Transfer-Encoding,当它读取到0\r\n\r\n时,认为已经读取到结尾了,但是剩下的字母G就被留在了缓冲区中,等待后续请求的到来。

当我们重复发送请求后,发送的请求在后端服务器拼接成了类似如下这种请求:


GPOST / HTTP/1.1\r\n

Host: ......


服务器在解析时就会产生报错。


利用http走私攻击,攻击者可以进行绕过前端服务器的安全控制、获取前端服务器重写请求字段、获取其他用户的请求、进行缓存投毒等攻击


防御建议

针对http走私攻击,通用的防御措施大概有三种:

Ø  禁用代理服务器与后端服务器之间的TCP连接重用。

Ø  使用HTTP/2协议。

Ø  前后端使用相同的服务器。



.   H2C走私攻击


通过HTTP走私,攻击者可以访问内部的服务器甚至是获得各种提权的机会。当前HTTP/1.1被广泛应用,但也暴露出一些问题,比如容易出现请求走私,使用HTTP/2可以解决走私,但是HTTP/2并不能完全防止走私


下面我们演示通过HTTP/2 without TLS(h2c)将HTTP/1.1连接升级到HTTP/2并且可以Bypass反向代理的访问控制,并且保持一个TCP长连接,导致HTTP请求不受反向代理的控制直接传送到后端服务器。


HTTP/2协议与H2C交换


通常HTTP/2协议在第一个HTTP请求之前,使用h2字符串进行标识,h2c是在Web协议从HTTP/1.1升级到HTTP/2的步骤中使用的标头。根据RFC-7540文档的描述,仅当客户端和服务器均支持HTTP/2时,才能使用HTTP / 2协议。


如何检测服务端是否支持HTTP/2:


1:客户端发起如下请求:


GET / HTTP/1.1

Host: test.example.com

Connection: Upgrade, HTTP2-Settings

Upgrade: h2c


2:如果支持HTTP/2,则服务器响应:


HTTP/1.1 101 Switching Protocols

Connection: Upgrade

Upgrade: h2c

[ HTTP/2 connection ...


3:如果不支持HTTP/2,则服务器响应:

Server ignored


如何将HTTP/1升级为HTTP/2:


当HTTP/1.x要升级到HTTP/2,标识符、HTTP2-Settings标头和Upgrade标头需要出现在http请求中。标识符的类型包括HTTP的h2c和HTTPS的h2。当Upgrade: h2c时,则以纯文本形式传递HTTP/2:


GET / HTTP/1.1

Host: test.example.com

Connection: Upgrade, HTTP2-Settings

Upgrade: h2c

HTTP2-Settings: <base64url encoding ofHTTP/2 SETTINGS payload>


在服务器支持HTTP/2时,它将101 Switching protocol转发到客户端并建立TLS连接(HTTP/2)与客户端进行通信。在这种情况下,使用TLS-ALPN协议。


在此过程中,使用APLN扩展名,客户端向服务器提供版本列表,然后服务器选择一个版本。同理,使用https时,HTTP/2选择h2。当直接使用HTTP/2时,通过TLS-ALPN进行协议协商之后,进行TLS连接。


H2C走私原理


许多Web服务都使用反向代理。在此过程中,当需要进行101 Switching时,代理服务器将充当中介,无需任何操作。通过阅读RFC文档和TLS中关于HTTP/2配置文档,里面声明只有明文连接才可以使用h2c升级,并且转发时不应包含HTTP2-Settings头。


具体走私流程如下图:


图片


1、客户端将HTTP/1.1升级请求发送到反向代理(发送了错误的标头);


2、代理将请求转发到后端,后端返回101 Swiching协议的响应,并准备接收HTTP/2通信;


3 .代理从后端服务器收到101响应时,将创建TCP隧道;


4 .客户端从代理接收到101响应时,将重新用现有TCP连接并执行HTTP/2初始化;


5 .客户端使用HTTP/2多路复用,发送针对受限资源的违法请求;


6 .由于代理服不监视TCP通信(HTTP通过策略),因此它将违法请求发送到受限页面;


7 .服务器响应,转发到TLS隧道,实现走私。



H2C走私演示


这里使用docker环境试验H2C走私,服务器使用nginx,docker-compose将模拟三条代理链,如下表所示。


TCP端口描述
8000
HTTP h2c后端
8001
HAProxy->h2c后端(不安全的默认配置)
8002
nginx->h2c后端(不安全自定义配置)
8003
Nuster->HAProxy->h2c后端(多层代理的不安全配置)


这些代理链将导致启用h2cGolang后端,如下图:


图片


所有代理都拒绝访问h2c后端上可访问的/flag节点。我们尝试通过在端口8001上运行的HAProxy服务器访问禁止的端点,如下图:


图片


使用h2cSmuggler工具来确认代理的不安全配置,如下图:


图片


使用h2cSmuggler执行h2c升级,通过代理对HTTP/2流量进行隧道传输,并从后端请求/flag端点,绕过代理的访问控制,如下图:


图片


如上所示,我们成功绕过了代理的访问控制来访问内部的HTTP接口!


防御建议

H2C具有减少带宽的能力,所以它非常适合用于低延迟的内部网络通信(微服务),避免了TLS的管理和(有争议但经常被提及的)性能开销。因此,流行的web框架通常支持一个配置选项来支持h2c升级,但是支持升级不是默认的,需要手动开启。如果前端代理配置不安全,在微服务中使用h2c可能会增加被成功攻击的可能性。


降低代理服务器上h2c走私的风险方式:


1、需要WebSocket支持:仅允许值WebSocket用于HTTP/1.1升级头(例如,upgrade:WebSocket)。


2、不需要WebSocket支持:不转发Upgrade请求头。


要使h2c走私成功,需要将升级头(有时是连接头)从边缘服务器成功转发到支持h2c升级的后端服务器。此配置可以发生在任何反向代理、WAF或负载平衡器上。


默认情况下,以下服务在代理传递过程中会转发Upgrade和Connection标头,从而使开箱即用的H2C走私成为可能:

Ø  HAProxy

Ø  Traefik

Ø  Nuster


默认情况下,这些服务在代理通常过程中不转发Upgrade和Connection标头,但可以以不安全的方式配置(通过传递未过滤的Upgrade和Connection标头):

Ø  AWS ALB/CLB

Ø  NGINX

Ø  Apache

Ø  Squid

Ø  Varnish

Ø  Kong

Ø  Envoy

Ø  Apache Traffic Server





 参考链接

https://v0w.top/2020/12/20/HTTPsmuggling

https://labs.bishopfox.com/tech-blog/h2c-smuggling-request-smuggling-via-http/2-cleartext-h2c

https://www.anquanke.com/post/id/220996



声明:该文观点仅代表作者本人,转载请注明来自看雪