Upgrade Header Smuggling

htARTE(HackTricks AWS Red Team Expert) でゼロからヒーローまでAWSハッキングを学ぶ

HackTricks をサポートする他の方法:

Try Hard Security Group


H2C スマグリング

HTTP2 Over Cleartext (H2C)

H2C、または http2 over cleartext は、標準のHTTP 接続を永続的なものにアップグレード することで、一時的なHTTP接続の通常から逸脱します。このアップグレードされた接続は、平文のHTTPの単一リクエストの性質とは異なり、継続的な通信のためにhttp2バイナリプロトコルを利用します。

スマグリングの問題の核心は、リバースプロキシの使用に起因します。通常、リバースプロキシはHTTPリクエストを処理し、バックエンドに転送してからバックエンドの応答を返します。しかし、HTTPリクエストに Connection: Upgrade ヘッダーが存在する場合(websocket接続で一般的に見られる)、リバースプロキシはクライアントとサーバー間の 永続的な接続を維持 し、特定のプロトコルで必要な連続した交換を容易にします。H2C接続の場合、RFCへの遵守には、3つの特定のヘッダーが存在する必要があります:

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

脆弱性は、接続をアップグレードした後、リバースプロキシが個々のリクエストを管理するのをやめ、ルーティングの仕事が接続確立後に完了したと仮定すると発生します。H2Cスマグリングを悪用すると、リクエスト処理中に適用されたリバースプロキシのルール(パスベースのルーティング、認証、WAF処理など)を回避できます。これは、H2C接続が正常に確立された場合に適用されます。

脆弱なプロキシ

脆弱性は、リバースプロキシがUpgradeおよび時折Connectionヘッダーを処理する方法に依存します。次のプロキシは、これらのヘッダーをプロキシパス中に暗黙的に転送し、それによってH2Cスマグリングを可能にします:

  • HAProxy

  • Traefik

  • Nuster

一方、これらのサービスはプロキシパス中に両方のヘッダーを暗黙的に転送しません。ただし、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バリアント(ConnectionヘッダーからHTTP2-Settings値を除外したもの)でテストする価値があります。一部のバックエンドは標準に準拠していないかもしれません。

proxy_pass URLで指定された特定のパス(例:http://backend:9999/socket.io)に関係なく、確立された接続はデフォルトでhttp://backend:9999になります。これにより、このテクニックを利用して、その内部エンドポイント内の任意のパスとやり取りできます。したがって、proxy_pass URLでパスを指定してもアクセスが制限されません。

BishopFoxのh2csmugglerassetnoteのh2csmugglerというツールは、H2C接続を確立することで、プロキシによって課せられた保護を回避し、リソースにアクセスできるようにする試みを支援します。

この脆弱性に関する詳細情報、特にNGINXに関する情報は、この詳細なリソースを参照してください。

Websocket Smuggling

Websocketスマグリングは、プロキシ経由でアクセス可能なエンドポイントへのHTTP2トンネルを作成するのとは異なり、プロキシの制限をバイパスし、エンドポイントとの直接通信を容易にするWebsocketトンネルを確立します。

シナリオ1

このシナリオでは、公開WebSocket APIを提供するバックエンドと、アクセスできない内部REST APIを持つバックエンドが、内部REST APIへのアクセスを求める悪意のあるクライアントによって標的にされます。攻撃は以下の手順で展開されます:

  1. クライアントは、ヘッダー内の正しくないSec-WebSocket-Versionプロトコルバージョンを持つUpgradeリクエストをリバースプロキシに送信します。リバースプロキシはSec-WebSocket-Versionヘッダーを検証できないため、Upgradeリクエストを有効と認識し、バックエンドに転送します。

  2. バックエンドは、Sec-WebSocket-Versionヘッダー内の誤ったプロトコルバージョンを示すステータスコード426で応答します。リバースプロキシはバックエンドの応答ステータスを見落とし、WebSocket通信の準備が整ったと誤解し、その応答をクライアントに中継します。

  3. 結果として、リバースプロキシは、クライアントとバックエンドの間にWebSocket接続が確立されたと誤解しますが、実際にはバックエンドがUpgradeリクエストを拒否していたため、そのような接続は存在しません。それにもかかわらず、プロキシはクライアントとバックエンドの間にオープンなTCPまたはTLS接続を維持し、クライアントがこの接続を介してプライベートREST APIに無制限にアクセスできるようにします。

影響を受けるリバースプロキシには、問題を解決しなかったVarnishや、バージョン1.8.0以前のEnvoyプロキシなどが含まれます。他のプロキシも影響を受ける可能性があります。

シナリオ2

このシナリオでは、公開WebSocket APIと公開REST API(ヘルスチェック用)を持つバックエンドと、アクセスできない内部REST APIが関与します。より複雑な攻撃は、以下の手順を含みます:

  1. クライアントは、ヘルスチェックAPIをトリガーするためにPOSTリクエストを送信し、追加のHTTPヘッダーUpgrade: websocketを含めます。リバースプロキシであるNGINXは、Upgradeヘッダーに基づいて標準のUpgradeリクエストとしてこれを解釈し、リクエストの他の側面を無視してバックエンドに転送します。

  2. バックエンドはヘルスチェックAPIを実行し、攻撃者が制御する外部リソースに到達してHTTPレスポンスを返します。このレスポンスは、バックエンドに受信され、NGINXに転送されると、ステータスコード101を持つHTTPレスポンスによって、プロキシはステータスコードのみを検証するため、WebSocket接続が確立されたと誤解します。

警告: このテクニックの複雑さは、ステータスコード101を返すエンドポイントとのやり取り能力が必要となるため、増加します。

最終的に、NGINXはクライアントとバックエンドの間にWebSocket接続が存在すると誤解されます。実際にはそのような接続は存在せず、ヘルスチェックREST APIが標的となります。それでも、リバースプロキシは接続を維持し、クライアントがこの接続を介してプライベートREST APIにアクセスできるようにします。

ほとんどのリバースプロキシはこのシナリオに対して脆弱ですが、悪用は一般に低重要度の問題と見なされる外部SSRF脆弱性の存在に依存します。

ラボ

両方のシナリオをテストするためのラボは、https://github.com/0ang3el/websocket-smuggle.gitで確認できます。

参考文献

Try Hard Security Group

htARTE(HackTricks AWS Red Team Expert)でAWSハッキングをゼロからヒーローまで学ぶ htARTE!

HackTricksをサポートする他の方法:

Last updated