hacktricks/pentesting-web/h2c-smuggling.md
2023-08-03 19:12:22 +00:00

10 KiB
Raw Blame History

升级头部欺骗

☁️ HackTricks 云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

H2C 欺骗

明文 HTTP2 (H2C)

通常,普通的 HTTP 连接只持续一个请求的时间。然而H2C 或者“明文 HTTP2”是指将普通的短暂的 HTTP 连接升级为使用 HTTP2 二进制协议进行持续通信的持久连接,而不是使用明文的 HTTP 协议进行一次请求。

欺骗的第二部分发生在使用反向代理时。通常,当向反向代理发送 HTTP 请求时,代理会处理请求,处理一系列路由规则,然后将请求转发到后端,然后返回响应。当 HTTP 请求包含 Connection: Upgrade 头部时,例如用于 WebSocket 连接,反向代理将维持客户端和服务器之间的持久连接允许这些协议所需的持续通信。对于 H2C 连接RFC 要求存在 3 个头部:

Upgrade: h2c
HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
Connection: Upgrade, HTTP2-Settings

漏洞位置

当升级连接时反向代理通常会停止处理单个请求假设一旦建立连接其路由工作就完成了。使用H2C Smuggling我们可以绕过反向代理在处理请求时使用的规则如基于路径的路由、身份验证或WAF处理只要我们能够首先建立H2C连接。

受影响的代理

根据漏洞的解释代理服务器需要转发Upgrade标头并且有时还需要成功转发Connection标头。

默认情况下以下服务在代理传递期间会转发Upgrade和Connection标头从而使h2c smuggling能够开箱即用

  • HAProxy
  • Traefik
  • Nuster

默认情况下这些服务在代理传递期间不会转发Upgrade和Connection标头但可以以不安全的方式进行配置通过传递未经过滤的Upgrade和Connection标头

  • AWS ALB/CLB
  • NGINX
  • Apache
  • Squid
  • Varnish
  • Kong
  • Envoy
  • Apache Traffic Server

攻击

原始博客文章指出并非所有服务器都会转发符合H2C连接升级所需的标头。这意味着默认情况下负载均衡器如AWS ALB/CLB、NGINX和Apache Traffic Server等将默认阻止H2C连接。然而在博客文章的最后他提到“并非所有后端都符合规范我们可以使用不符合规范的Connection: Upgrade变体进行测试,其中HTTP2-Settings值从Connection标头中省略”。

{% hint style="danger" %} 请注意,即使proxy_pass URL代理转发连接的终点指向特定的路径例如http://backend:9999/socket.io,连接也将与http://backend:9999建立因此您可以滥用此技术来联系该内部终点中的任何其他路径。因此在proxy_pass的URL中指定路径无关紧要。 {% endhint %}

使用工具https://github.com/BishopFox/h2csmugglerhttps://github.com/assetnote/h2csmuggler您可以尝试绕过代理所施加的保护建立H2C连接并访问受代理保护的资源。

点击此链接获取有关Nginx中此漏洞的更多信息

WebSocket Smuggling

与之前的技术类似这个技术不是创建到通过代理可访问的端点的HTTP2隧道而是为相同目的创建一个WebSocket隧道绕过潜在的代理限制并直接与端点通信

场景1

我们有一个后端,公开暴露了WebSocket API,并且还有一个无法从外部访问的内部REST API。恶意客户端想要访问内部REST API。

第一步中,客户端发送升级请求到反向代理,但在标头Sec-WebSocket-Version中使用了错误的协议版本代理不验证Sec-WebSocket-Version标头,并认为升级请求是正确的。然后,它将请求转发到后端。

在第二步中,后端发送带有状态码426的响应,因为标头Sec-WebSocket-Version中的协议版本不正确。然而,反向代理不会检查来自后端的足够响应(包括状态码),并认为后端已准备好进行WebSocket通信。然后,它将请求转发到客户端。

最后,反向代理认为客户端和后端之间建立了WebSocket连接。实际上并没有WebSocket连接 - 后端拒绝了升级请求。同时代理保持客户端和后端之间的TCP或TLS连接处于打开状态。客户端可以通过在连接上发送HTTP请求轻松访问私有REST API

已发现以下反向代理受到影响:

  • Varnish - 团队拒绝修复所描述的问题。
  • Envoy proxy 1.8.0(或更旧版本)- 在更新的版本中,升级机制已更改。
  • 其他 - 待定。

场景2

大多数反向代理例如NGINX在握手部分期间检查来自后端的状态码。这使得攻击更加困难,但并非不可能。

让我们观察第二个场景。我们有一个后端公开暴露了WebSocket API和用于健康检查的公共REST API同时还有无法从外部访问的内部REST API。恶意客户端想要访问内部REST API。NGINX用作反向代理。WebSocket API在路径/api/socket.io/上可用健康检查API在路径/api/health上可用。

通过发送POST请求来调用健康检查API名为u的参数控制URL。后端访问由恶意用户控制的外部资源并将状态码返回给客户端。

第一步客户端发送POST请求来调用健康检查API但附加了HTTP标头Upgrade: websocket。NGINX认为这是一个正常的升级请求,它只查找Upgrade标头,跳过请求的其他部分。然后代理将请求转发到后端。

第二步后端调用健康检查API。它访问由恶意用户控制的外部资源并返回带有状态码101的HTTP响应。后端将该响应转发给反向代理。由于NGINX仅验证状态码它将认为后端已准备好进行WebSocket通信。然后,它将请求转发到客户端。

{% hint style="warning" %} 请注意,这种情况要更难利用,因为您需要能够联系某个返回状态码101的端点。 {% endhint %}

最后,NGINX认为WebSocket连接已在客户端和后端之间建立。实际上并没有WebSocket连接 - 后端调用了健康检查REST API。同时反向代理保持客户端和后端之间的TCP或TLS连接处于打开状态。客户端可以通过在连接上发送HTTP请求轻松访问私有REST API

大多数反向代理应该受到该场景的影响。然而利用需要存在外部SSRF漏洞通常被认为是低严重性问题

实验室

检查实验室以测试两种情况:https://github.com/0ang3el/websocket-smuggle.git

参考资料

☁️ HackTricks 云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥