HTTP Request Smuggling / HTTP Desync Attack
Last updated
Last updated
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する: HackTricks Training GCP Red Team Expert (GRTE)
あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る
実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告に変えます。
この脆弱性は、フロントエンドプロキシとバックエンドサーバーの間に非同期化が発生し、攻撃者がHTTP リクエストを送信できるときに発生します。このリクエストはフロントエンドプロキシ(ロードバランス/リバースプロキシ)によって単一のリクエストとして解釈され、バックエンドサーバーによって2つのリクエストとして解釈されます。 これにより、ユーザーはバックエンドサーバーに到着する次のリクエストを変更することができます。
メッセージが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-Length
とNormalize HTTP/1 line endings
を無効にしてください。一部のガジェットは新しい行、キャリッジリターン、誤ったContent-Lengthを悪用します。
HTTPリクエストスムーギング攻撃は、フロントエンドとバックエンドサーバーがContent-Length
(CL)およびTransfer-Encoding
(TE)ヘッダーを解釈する際の不一致を利用して、あいまいなリクエストを送信することによって作成されます。これらの攻撃は、主にCL.TE、TE.CL、およびTE.TEとして異なる形で現れます。各タイプは、フロントエンドとバックエンドサーバーがこれらのヘッダーを優先する方法のユニークな組み合わせを表します。脆弱性は、サーバーが同じリクエストを異なる方法で処理することから生じ、予期しない、そして潜在的に悪意のある結果をもたらします。
前の表にTE.0技術を追加する必要があります。CL.0技術のように、Transfer Encodingを使用します。
フロントエンド (CL): Content-Length
ヘッダーに基づいてリクエストを処理します。
バックエンド (TE): Transfer-Encoding
ヘッダーに基づいてリクエストを処理します。
攻撃シナリオ:
攻撃者は、Content-Length
ヘッダーの値が実際のコンテンツ長と一致しないリクエストを送信します。
フロントエンドサーバーは、Content-Length
の値に基づいてリクエスト全体をバックエンドに転送します。
バックエンドサーバーは、Transfer-Encoding: chunked
ヘッダーによりリクエストをチャンクとして処理し、残りのデータを別の後続リクエストとして解釈します。
例:
フロントエンド (TE): Transfer-Encoding
ヘッダーに基づいてリクエストを処理します。
バックエンド (CL): Content-Length
ヘッダーに基づいてリクエストを処理します。
攻撃シナリオ:
攻撃者は、チャンクサイズ(7b
)と実際のコンテンツ長(Content-Length: 4
)が一致しないチャンクリクエストを送信します。
フロントエンドサーバーは、Transfer-Encoding
を尊重し、リクエスト全体をバックエンドに転送します。
バックエンドサーバーは、Content-Length
を尊重し、リクエストの最初の部分(7b
バイト)だけを処理し、残りを意図しない後続リクエストの一部として残します。
例:
サーバー: 両方ともTransfer-Encoding
をサポートしていますが、一方は難読化を介して無視されるように騙される可能性があります。
攻撃シナリオ:
攻撃者は、難読化されたTransfer-Encoding
ヘッダーを持つリクエストを送信します。
どちらのサーバー(フロントエンドまたはバックエンド)が難読化を認識できないかによって、CL.TEまたはTE.CLの脆弱性が悪用される可能性があります。
リクエストの未処理部分は、サーバーの1つによって見られ、後続のリクエストの一部となり、スムーギングが発生します。
例:
両方のサーバーは、Content-Length
ヘッダーのみに基づいてリクエストを処理します。
このシナリオは通常、スムーギングには至らず、両方のサーバーがリクエストの長さを解釈する方法に整合性があります。
例:
Content-Length
ヘッダーが存在し、ゼロ以外の値を持ち、リクエストボディにコンテンツがあることを示すシナリオを指します。バックエンドはContent-Length
ヘッダーを無視します(これは0として扱われます)が、フロントエンドはそれを解析します。
スムーギング攻撃を理解し、作成する上で重要であり、サーバーがリクエストの終わりを決定する方法に影響を与えます。
例:
前のものと同様ですが、TEを使用します。
技術はこちらで報告されています
例:
この技術は、初期のHTTPデータを読み取る際にウェブサーバーを破壊することが可能なシナリオでも有用ですが、接続を閉じることなく行います。この方法では、HTTPリクエストのボディが次のHTTPリクエストとして扱われます。
例えば、この書き込みで説明されているように、WerkzeugではいくつかのUnicode文字を送信することでサーバーが破壊されることが可能でした。しかし、HTTP接続が**Connection: keep-alive
ヘッダーで作成された場合、リクエストのボディは読み取られず、接続はまだオープンのままとなるため、リクエストのボディは次のHTTPリクエスト**として扱われます。
ホップバイホップヘッダーを悪用することで、プロキシにContent-LengthまたはTransfer-Encodingヘッダーを削除させることができ、HTTPリクエストスムージングを悪用することが可能です。
For more information about hop-by-hop headers visit:
hop-by-hop headersHTTPリクエストスムージングの脆弱性を特定するには、サーバーが操作されたリクエストに応答するのにかかる時間を観察するタイミング技術を使用することがよくあります。これらの技術は、特にCL.TEおよびTE.CLの脆弱性を検出するのに役立ちます。これらの方法に加えて、他にもこのような脆弱性を見つけるために使用できる戦略やツールがあります。
方法:
アプリケーションが脆弱な場合、バックエンドサーバーが追加データを待機するリクエストを送信します。
例:
観察:
フロントエンドサーバーはContent-Length
に基づいてリクエストを処理し、メッセージを早期に切り捨てます。
バックエンドサーバーはチャンクメッセージを期待しており、決して到着しない次のチャンクを待機するため、遅延が発生します。
指標:
タイムアウトや応答の長い遅延。
バックエンドサーバーから400 Bad Requestエラーを受信することがあり、時には詳細なサーバー情報が含まれます。
方法:
アプリケーションが脆弱な場合、バックエンドサーバーが追加データを待機するリクエストを送信します。
例:
観察:
フロントエンドサーバーはTransfer-Encoding
に基づいてリクエストを処理し、メッセージ全体を転送します。
バックエンドサーバーはContent-Length
に基づいてメッセージを期待しており、決して到着しない追加データを待機するため、遅延が発生します。
差分応答分析:
リクエストのわずかに異なるバージョンを送信し、サーバーの応答が予期しない方法で異なるかどうかを観察し、解析の不一致を示します。
自動化ツールの使用:
Burp Suiteの「HTTP Request Smuggler」拡張機能のようなツールは、さまざまな形式のあいまいなリクエストを送信し、応答を分析することでこれらの脆弱性を自動的にテストできます。
Content-Lengthの変動テスト:
実際のコンテンツ長と一致しないさまざまなContent-Length
値を持つリクエストを送信し、サーバーがそのような不一致をどのように処理するかを観察します。
Transfer-Encodingの変動テスト:
難読化または不正なTransfer-Encoding
ヘッダーを持つリクエストを送信し、フロントエンドとバックエンドサーバーがそのような操作にどのように異なる応答を示すかを監視します。
タイミング技術の効果を確認した後、クライアントリクエストを操作できるかどうかを検証することが重要です。簡単な方法は、リクエストを毒することを試みることです。たとえば、/
へのリクエストが404応答を返すようにします。前述の基本的な例で説明したCL.TE
およびTE.CL
の例は、クライアントのリクエストを毒して404応答を引き出す方法を示していますが、クライアントは異なるリソースにアクセスしようとしています。
重要な考慮事項
他のリクエストに干渉してリクエストスムージングの脆弱性をテストする際には、次の点に留意してください。
異なるネットワーク接続: 「攻撃」と「正常」リクエストは、別々のネットワーク接続を介して送信する必要があります。両方のリクエストに同じ接続を使用することは、脆弱性の存在を検証しません。
一貫したURLとパラメータ: 両方のリクエストに対して同一のURLとパラメータ名を使用することを目指してください。現代のアプリケーションは、URLとパラメータに基づいてリクエストを特定のバックエンドサーバーにルーティングすることがよくあります。これらを一致させることで、両方のリクエストが同じサーバーによって処理される可能性が高まり、成功する攻撃の前提条件となります。
タイミングとレース条件: 「正常」リクエストは、「攻撃」リクエストからの干渉を検出するために設計されており、他の同時アプリケーションリクエストと競合します。したがって、「攻撃」リクエストの直後に「正常」リクエストを送信してください。忙しいアプリケーションでは、脆弱性の確認のために複数の試行が必要になる場合があります。
負荷分散の課題: フロントエンドサーバーが負荷分散装置として機能している場合、リクエストをさまざまなバックエンドシステムに分配することがあります。「攻撃」と「正常」リクエストが異なるシステムに到達した場合、攻撃は成功しません。この負荷分散の側面は、脆弱性を確認するためにいくつかの試行を必要とする場合があります。
意図しないユーザーへの影響: あなたの攻撃が他のユーザーのリクエスト(検出のために送信した「正常」リクエストではない)に偶然影響を与える場合、これはあなたの攻撃が他のアプリケーションユーザーに影響を与えたことを示します。継続的なテストは他のユーザーを混乱させる可能性があるため、慎重なアプローチが必要です。
時には、フロントエンドプロキシがセキュリティ対策を強化し、受信リクエストを精査します。しかし、これらの対策はHTTPリクエストスムージングを利用することで回避でき、制限されたエンドポイントへの不正アクセスを可能にします。たとえば、/admin
へのアクセスは外部から禁止されている場合があり、フロントエンドプロキシがそのような試みを積極的にブロックしています。それにもかかわらず、このプロキシはスムージングされたHTTPリクエスト内の埋め込まれたリクエストを検査しない可能性があり、これらの制限を回避するための抜け穴を残します。
以下の例は、HTTPリクエストスムージングがどのようにしてフロントエンドのセキュリティ制御を回避するために使用できるかを示しています。特に、通常フロントエンドプロキシによって保護されている/admin
パスをターゲットにしています。
CL.TEの例
CL.TE攻撃では、最初のリクエストにContent-Length
ヘッダーが利用され、次の埋め込まれたリクエストはTransfer-Encoding: chunked
ヘッダーを使用します。フロントエンドプロキシは最初のPOST
リクエストを処理しますが、埋め込まれたGET /admin
リクエストを検査できず、/admin
パスへの不正アクセスを許可します。
TE.CL 例
逆に、TE.CL攻撃では、最初のPOST
リクエストがTransfer-Encoding: chunked
を使用し、その後の埋め込まれたリクエストはContent-Length
ヘッダーに基づいて処理されます。CL.TE攻撃と同様に、フロントエンドプロキシは密輸されたGET /admin
リクエストを見落とし、意図せずに制限された/admin
パスへのアクセスを許可します。
アプリケーションは、通常、フロントエンドサーバーを使用して、バックエンドサーバーに渡す前に受信リクエストを変更します。典型的な変更には、クライアントのIPをバックエンドに中継するためにX-Forwarded-For: <IP of the client>
のようなヘッダーを追加することが含まれます。これらの変更を理解することは重要であり、保護を回避する方法や隠された情報やエンドポイントを明らかにする方法を示す可能性があります。
プロキシがリクエストをどのように変更するかを調査するには、バックエンドがレスポンスでエコーするPOSTパラメータを見つけます。次に、このパラメータを最後に使用してリクエストを作成します。以下のように:
この構造では、後続のリクエストコンポーネントが search=
の後に追加され、これはレスポンスに反映されるパラメータです。この反映により、後続のリクエストのヘッダーが露出します。
ネストされたリクエストの Content-Length
ヘッダーを実際のコンテンツ長に合わせることが重要です。小さな値から始めて徐々に増加させることが推奨されます。値が低すぎると反映されたデータが切り捨てられ、高すぎるとリクエストがエラーになる可能性があります。
この技術は TE.CL 脆弱性の文脈でも適用可能ですが、リクエストは search=\r\n0
で終了する必要があります。改行文字に関係なく、値は検索パラメータに追加されます。
この方法は、フロントエンドプロキシによって行われたリクエストの変更を理解するために主に使用され、基本的には自己主導の調査を行います。
POST 操作中に特定のリクエストをパラメータの値として追加することで、次のユーザーのリクエストをキャプチャすることが可能です。これを実現する方法は次のとおりです:
次のリクエストをパラメータの値として追加することで、後続のクライアントのリクエストを保存できます:
このシナリオでは、commentパラメータは、公開アクセス可能なページの投稿のコメントセクション内の内容を保存することを目的としています。その結果、次のリクエストの内容はコメントとして表示されます。
しかし、この技術には制限があります。一般的に、これはスムーズにリクエストで使用されるパラメータ区切り文字までのデータしかキャプチャしません。URLエンコードされたフォーム送信の場合、この区切り文字は&
文字です。これは、被害者ユーザーのリクエストからキャプチャされた内容が最初の&
で止まることを意味し、これはクエリ文字列の一部である可能性さえあります。
さらに、このアプローチはTE.CL脆弱性でも有効であることに注意する価値があります。その場合、リクエストはsearch=\r\n0
で終了する必要があります。改行文字に関係なく、値は検索パラメータに追加されます。
HTTPリクエストスムージングは、反射型XSSに脆弱なウェブページを悪用するために利用でき、重要な利点を提供します:
対象ユーザーとの対話は不要です。
HTTPリクエストヘッダーのような、通常は到達不可能なリクエストの部分でXSSを悪用することができます。
ウェブサイトがUser-Agentヘッダーを通じて反射型XSSに対して脆弱な場合、以下のペイロードはこの脆弱性を悪用する方法を示しています:
このペイロードは、脆弱性を悪用するために構成されています:
Transfer-Encoding: chunked
ヘッダーを持つ、見た目には典型的な POST
リクエストを開始し、スムーギングの開始を示します。
次に、チャンクメッセージボディの終わりを示す 0
が続きます。
その後、スムーグルされた GET
リクエストが導入され、User-Agent
ヘッダーにスクリプト <script>alert(1)</script>
が注入され、サーバーがこの後続のリクエストを処理する際に XSS がトリガーされます。
スムーギングを通じて User-Agent
を操作することで、ペイロードは通常のリクエスト制約を回避し、非標準だが効果的な方法で反射型 XSS 脆弱性を悪用します。
ユーザーコンテンツが Content-type
が text/plain
のレスポンスに反映される場合、XSS の実行が防止されます。サーバーが HTTP/0.9 をサポートしている場合、これを回避できる可能性があります!
HTTP/0.9 バージョンは 1.0 の前のもので、GET 動詞のみを使用し、ヘッダー ではなくボディのみで応答します。
この書き込み では、リクエストスムーギングと ユーザーの入力に応じて応答する脆弱なエンドポイント を利用して、HTTP/0.9 でリクエストをスムーグルしました。レスポンスに反映されるパラメータには 偽の HTTP/1.1 レスポンス(ヘッダーとボディを含む) が含まれているため、レスポンスには Content-Type
が text/html
の有効な実行可能な JS コードが含まれます。
アプリケーションは、リダイレクト URL の Host
ヘッダーからホスト名を使用して、ある URL から別の URL にリダイレクトすることがよくあります。これは、Apache や IIS のようなウェブサーバーで一般的です。たとえば、末尾にスラッシュがないフォルダーをリクエストすると、スラッシュを含めるためにリダイレクトされます:
結果は次のとおりです:
この無害に見える動作は、HTTPリクエストスムーギングを使用してユーザーを外部サイトにリダイレクトするように操作できます。例えば:
このスムグルリクエストは、次に処理されるユーザーリクエストが攻撃者が制御するウェブサイトにリダイレクトされる原因となる可能性があります:
結果は:
このシナリオでは、ユーザーのJavaScriptファイルへのリクエストがハイジャックされます。攻撃者は、悪意のあるJavaScriptを応答として提供することで、ユーザーを危険にさらす可能性があります。
ウェブキャッシュポイズニングは、フロントエンドインフラストラクチャがコンテンツをキャッシュする任意のコンポーネントがある場合に実行できます。通常、これはパフォーマンスを向上させるためです。サーバーの応答を操作することで、キャッシュをポイズンすることが可能です。
以前、サーバーの応答を変更して404エラーを返す方法を観察しました(基本的な例を参照)。同様に、サーバーを騙して/static/include.js
へのリクエストに対して/index.html
のコンテンツを提供させることも可能です。その結果、/static/include.js
のコンテンツはキャッシュ内で/index.html
のものに置き換えられ、ユーザーが/static/include.js
にアクセスできなくなり、サービス拒否(DoS)につながる可能性があります。
この技術は、オープンリダイレクトの脆弱性が発見された場合や、オープンリダイレクトへのオンサイトリダイレクトがある場合に特に強力になります。このような脆弱性を利用して、攻撃者の制御下にあるスクリプトで/static/include.js
のキャッシュされたコンテンツを置き換えることができ、実質的にすべてのクライアントに対して広範なクロスサイトスクリプティング(XSS)攻撃を可能にします。
以下は、オープンリダイレクトへのオンサイトリダイレクトと組み合わせたキャッシュポイズニングの悪用の例です。目的は、攻撃者が制御するJavaScriptコードを提供するために/static/include.js
のキャッシュコンテンツを変更することです:
埋め込まれたリクエストが /post/next?postId=3
をターゲットにしていることに注意してください。このリクエストは /post?postId=4
にリダイレクトされ、Host ヘッダーの値を利用してドメインを決定します。Host ヘッダーを変更することで、攻撃者はリクエストを自分のドメインにリダイレクトできます(オンサイトリダイレクトからオープンリダイレクト)。
成功した ソケットポイズニング の後、/static/include.js
に対する GET リクエスト を開始する必要があります。このリクエストは、以前の オンサイトリダイレクトからオープンリダイレクト リクエストによって汚染され、攻撃者が制御するスクリプトの内容を取得します。
その後、/static/include.js
に対するリクエストは、攻撃者のスクリプトのキャッシュされた内容を提供し、効果的に広範な XSS 攻撃を開始します。
ウェブキャッシュポイズニングとウェブキャッシュの欺瞞の違いは何ですか?
ウェブキャッシュポイズニング では、攻撃者がアプリケーションに悪意のあるコンテンツをキャッシュに保存させ、そのコンテンツが他のアプリケーションユーザーにキャッシュから提供されます。
ウェブキャッシュの欺瞞 では、攻撃者がアプリケーションに他のユーザーに属する機密コンテンツをキャッシュに保存させ、攻撃者がそのコンテンツをキャッシュから取得します。
攻撃者は、機密のユーザー固有のコンテンツを取得するためのスムージングリクエストを作成します。次の例を考えてみてください:
このスムグルされたリクエストが静的コンテンツ(例:/someimage.png
)用のキャッシュエントリを汚染すると、被害者の/private/messages
からの機密データが静的コンテンツのキャッシュエントリの下にキャッシュされる可能性があります。その結果、攻撃者はこれらのキャッシュされた機密データを取得できる可能性があります。
この投稿では、サーバーにTRACEメソッドが有効になっている場合、HTTPリクエストスムグリングを利用することが可能であると提案されています。これは、このメソッドがサーバーに送信された任意のヘッダーをレスポンスのボディの一部として反映するためです。例えば:
以下のようなレスポンスを送信します:
この動作を悪用する例としては、最初にHEADリクエストをスムグルことが挙げられます。このリクエストには、GETリクエストのヘッダーのみが応答されます(その中に**Content-Type
が含まれます)。そして、HEADの直後にTRACEリクエストをスムグルことで、送信されたデータを反映させることができます。
HEADの応答にはContent-Length
ヘッダーが含まれるため、TRACEリクエストの応答はHEAD応答のボディとして扱われ、したがって任意のデータを反映させることになります。
この応答は接続上の次のリクエストに送信されるため、例えばキャッシュされたJSファイルで任意のJSコードを注入するために使用される可能性があります**。
この投稿を引き続き参照することが推奨されており、TRACEメソッドを悪用する別の方法が示されています。コメントの通り、HEADリクエストとTRACEリクエストをスムグルことで、HEADリクエストへの応答における一部の反映データを制御することが可能です。HEADリクエストのボディの長さは基本的にContent-Lengthヘッダーで示され、TRACEリクエストへの応答によって形成されます。
したがって、新しいアイデアは、このContent-LengthとTRACE応答で与えられたデータを知ることで、TRACE応答がContent-Lengthの最後のバイトの後に有効なHTTP応答を含むようにすることが可能であり、攻撃者が次の応答へのリクエストを完全に制御できるようにすることです(これによりキャッシュポイズニングを実行することができます)。
例:
これらのレスポンスを生成します(HEADレスポンスにContent-Lengthがあることに注意してください。これによりTRACEレスポンスがHEADボディの一部となり、HEAD Content-Lengthが終了すると有効なHTTPレスポンスがスムーズに送信されます):
HTTPリクエストスムーギングの脆弱性を見つけたが、どのように悪用するかわからない場合は、他の悪用方法を試してみてください。
HTTP Response Smuggling / DesyncブラウザHTTPリクエストスムーギング(クライアントサイド)
HTTP/2ダウングレードにおけるリクエストスムーギング
From https://hipotermia.pw/bb/http-desync-idor
From: https://hipotermia.pw/bb/http-desync-account-takeover
https://github.com/bahruzjabiyev/t-reqs-http-fuzzer: このツールは、奇妙なリクエストスムーギングの不一致を見つけるのに役立つ文法ベースのHTTPファズァです。
あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る
実際のビジネスに影響を与える重要で悪用可能な脆弱性を見つけて報告します。 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告に変えます。
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する: HackTricks Training GCP Red Team Expert (GRTE)