アップグレードヘッダーのスムーギング

Reading time: 11 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

H2Cスムーギング

HTTP2オーバークリアテキスト (H2C)

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

スムーギングの問題の核心は、リバースプロキシの使用にあります。通常、リバースプロキシはHTTPリクエストを処理し、バックエンドに転送し、その後バックエンドの応答を返します。しかし、HTTPリクエストにConnection: Upgradeヘッダーが存在する場合(一般的にウェブソケット接続で見られる)、リバースプロキシはクライアントとサーバーの間に持続的な接続を維持し、特定のプロトコルに必要な継続的な交換を促進します。H2C接続の場合、RFCに従うためには、3つの特定のヘッダーが必要です:

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

脆弱性は、接続をアップグレードした後、リバースプロキシが個々のリクエストの管理を停止し、接続確立後にルーティングの仕事が完了したと仮定する場合に発生します。H2C Smugglingを利用することで、リクエスト処理中に適用されるリバースプロキシのルール(パスベースのルーティング、認証、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値を除外します。一部のバックエンドは標準に準拠していない可能性があります。

caution

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

ツールh2csmuggler by BishopFoxおよびh2csmuggler by assetnoteは、H2C接続を確立することにより、プロキシによって課せられた保護を回避する試みを支援し、プロキシによって保護されたリソースへのアクセスを可能にします。

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

Websocket Smuggling

Websocket smugglingは、プロキシを介してアクセス可能なエンドポイントへの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や、アップグレードメカニズムが変更されたEnvoyプロキシバージョン1.8.0以前が含まれます。他のプロキシも脆弱である可能性があります。

https://github.com/0ang3el/websocket-smuggle/raw/master/img/2-4.png

シナリオ2

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

  1. クライアントは、健康チェックAPIをトリガーするためにPOSTリクエストを送信し、追加のHTTPヘッダーUpgrade: websocketを含めます。リバースプロキシとして機能するNGINXは、Upgradeヘッダーのみに基づいてこれを標準のUpgradeリクエストとして解釈し、リクエストの他の側面を無視してバックエンドに転送します。
  2. バックエンドは健康チェックAPIを実行し、攻撃者が制御する外部リソースに接続し、ステータスコード101のHTTP応答を返します。この応答はバックエンドによって受信され、NGINXに転送されると、プロキシはステータスコードのみを検証してWebSocket接続が確立されたと誤解します。

https://github.com/0ang3el/websocket-smuggle/raw/master/img/3-4.png

警告: この技術の複雑さは、ステータスコード101を返すことができるエンドポイントと対話する能力を必要とするため、増加します。

最終的に、NGINXはクライアントとバックエンドの間にWebSocket接続が存在すると誤解します。実際には、そのような接続は存在せず、健康チェックREST APIがターゲットでした。それにもかかわらず、リバースプロキシは接続をオープンに保ち、クライアントがそれを通じてプライベートREST APIにアクセスできるようにします。

https://github.com/0ang3el/websocket-smuggle/raw/master/img/3-5.png

ほとんどのリバースプロキシはこのシナリオに脆弱ですが、悪用は外部SSRF脆弱性の存在に依存し、通常は低Severityの問題と見なされます。

ラボ

両方のシナリオをテストするためのラボを確認してください https://github.com/0ang3el/websocket-smuggle.git

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする