16 KiB
Raw Blame History

特殊なHTTPヘッダー

{{#include ../../banners/hacktricks-training.md}}

ワードリストとツール

ロケーションを変更するヘッダー

IPの送信元を書き換える:

  • X-Originating-IP: 127.0.0.1
  • X-Forwarded-For: 127.0.0.1
  • X-Forwarded: 127.0.0.1
  • Forwarded-For: 127.0.0.1
  • X-Forwarded-Host: 127.0.0.1
  • X-Remote-IP: 127.0.0.1
  • X-Remote-Addr: 127.0.0.1
  • X-ProxyUser-Ip: 127.0.0.1
  • X-Original-URL: 127.0.0.1
  • Client-IP: 127.0.0.1
  • X-Client-IP: 127.0.0.1
  • X-Host: 127.0.0.1
  • 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 (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 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 はオブジェクトが 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-cacheCache-Control: no-cache と同じ
  • Warning: 一般的な HTTP ヘッダーで、メッセージの状態に関する可能性のある問題についての情報を含む。レスポンスに複数の Warning ヘッダーが含まれることがある。Warning: 110 anderson/1.3.37 "Response is stale"

条件付きリクエスト

  • If-Modified-SinceIf-Unmodified-Since を用いたリクエストは、レスポンスヘッダー Last-Modified が異なる日時を含む場合にのみデータが返される。
  • If-MatchIf-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 または日付がリモートリソースと一致する場合にのみ実行される条件付き範囲リクエストを作成する。互換性のないバージョンのリソースから二つの範囲をダウンロードしてしまうのを防ぐために使われる。
  • Content-Range: 部分メッセージが完全な本文メッセージのどこに属するかを示す。

メッセージ本文情報

  • Content-Length: リソースのサイズ(十進数のバイト数)。
  • Content-Type: リソースのメディアタイプを示す。
  • Content-Encoding: 圧縮アルゴリズムを指定するために使われる。
  • Content-Language: 対象となる利用者向けの自然言語を記述し、ユーザーが好みの言語に応じて区別できるようにする。
  • Content-Location: 返却されるデータの代替場所を示す。

pentest の観点ではこの情報は通常役に立たないことが多いですが、リソースが 401 や 403 で保護されていて、何らかの方法でこの情報を取得できる場合は興味深いことがあります。例えば HEAD リクエストで RangeEtag を組み合わせることで、HEAD リクエスト経由でページの内容が leak することがあります:

  • ヘッダー Range: bytes=20-20 を付けたリクエストと、レスポンスに ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y" が含まれる場合、バイト20の SHA1 が ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y であることが leak している。

サーバー情報

  • Server: Apache/2.4.1 (Unix)
  • X-Powered-By: PHP/5.3.3

コントロール

  • Allow: このヘッダーはリソースが扱える HTTP メソッドを伝えるために使われる。例えば Allow: GET, POST, HEAD はそのリソースがこれらのメソッドをサポートしていることを示す。
  • Expect: クライアントがリクエストを正常に処理するためにサーバーが満たすべき期待を伝えるために用いられる。一般的なユースケースは Expect: 100-continue ヘッダーで、クライアントが大きなデータペイロードを送信する意図があることを示す。クライアントは送信を続行する前に 100 (Continue) レスポンスを待ち、これによりサーバーの確認を待つことでネットワーク利用を最適化できる。

ダウンロード

HTTP レスポンス内の Content-Disposition ヘッダーは、ファイルをウェブページ内に表示するinlineか、添付ファイルとして扱ってダウンロードさせるattachmentかを指示します。例えば:

Content-Disposition: attachment; filename="filename.jpg"

これは "filename.jpg" という名前のファイルがダウンロードされ保存されることを意図していることを意味します。

セキュリティヘッダー

コンテンツセキュリティポリシー (CSP)

{{#ref}} ../../pentesting-web/content-security-policy-csp-bypass/ {{#endref}}

Trusted Types

CSPを通じてTrusted Typesを強制することで、アプリケーションはDOM XSS攻撃から保護されます。Trusted Typesは、確立されたセキュリティポリシーに準拠した特別に作成されたオブジェクトのみが危険な web API 呼び出しで使用できるようにすることで、JavaScriptコードをデフォルトで保護します。

// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
// Name and create a policy
const policy = trustedTypes.createPolicy('escapePolicy', {
createHTML: str => str.replace(/\</g, '&lt;').replace(/>/g, '&gt;');
});
}
// Assignment of raw strings is blocked, ensuring safety.
el.innerHTML = "some string" // Throws an exception.
const escaped = policy.createHTML("<img src=x onerror=alert(1)>")
el.innerHTML = escaped // Results in safe assignment.

X-Content-Type-Options

このヘッダーはMIMEタイプのスニッフィングを防ぎ、XSS脆弱性を引き起こす可能性のある挙動を抑えます。ブラウザがサーバーで指定されたMIMEタイプを尊重するようにします。

X-Content-Type-Options: nosniff

X-Frame-Options

clickjacking に対抗するため、このヘッダーはドキュメントが <frame><iframe><embed>、または <object> タグにどのように埋め込まれるかを制限し、すべてのドキュメントで埋め込み許可を明示的に指定することを推奨します。

X-Frame-Options: DENY

クロスオリジンリソースポリシー (CORP) と クロスオリジンリソース共有 (CORS)

CORP は、どのリソースがウェブサイトによって読み込まれるかを指定する上で重要であり、cross-site leaks を軽減します。CORS は、一方でより柔軟なクロスオリジンリソース共有の仕組みを提供し、特定の条件下で same-origin policy を緩和します。

Cross-Origin-Resource-Policy: same-origin
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Cross-Origin Embedder Policy (COEP) と Cross-Origin Opener Policy (COOP)

COEP と COOP はクロスオリジン隔離を有効にするために不可欠で、Spectre のような攻撃のリスクを大幅に低減します。
それぞれ、クロスオリジンリソースの読み込みとクロスオリジンウィンドウとの相互作用を制御します。

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin-allow-popups

HTTP Strict Transport Security (HSTS)

最後に、HSTSはブラウザがサーバーと安全なHTTPS接続でのみ通信するよう強制するセキュリティ機能であり、これによりプライバシーとセキュリティが向上します。

Strict-Transport-Security: max-age=3153600

ヘッダ名の大文字小文字によるバイパス

HTTP/1.1 はヘッダフィールド名を 大文字小文字を区別しない と定義しています (RFC 9110 §5.1)。それにもかかわらず、カスタムミドルウェア、セキュリティフィルタ、ビジネスロジックの中には、受信したヘッダ名を大文字小文字正規化せずにそのまま比較する実装(例: header.equals("CamelExecCommandExecutable"))がよく見られます。これらのチェックが 大文字小文字を区別して 行われている場合、攻撃者は単に異なる大文字小文字で同じヘッダを送ることでバイパスできる可能性があります。

典型的な発生場面:

  • 機密コンポーネントに到達する前に「危険な」内部ヘッダをブロックしようとするカスタムの許可/拒否リスト。
  • リバースプロキシの疑似ヘッダを自社実装しているケース(例: X-Forwarded-For のサニタイズ)。
  • 管理/デバッグ用エンドポイントを公開し、認証やコマンド選択にヘッダ名を利用しているフレームワーク。

バイパスの悪用

  1. サーバ側でフィルタリングまたは検証されているヘッダを特定する(例: ソースコード、ドキュメント、エラーメッセージを読む)。
  2. 同じヘッダを異なる大文字小文字で送る混合ケースや全大文字など。HTTPスタックは通常ユーザコード実行後にヘッダを正規化するため、脆弱なチェックを回避できることがある。
  3. 下流のコンポーネントがヘッダを大文字小文字を区別しない方法で扱う(ほとんどはそうする)場合、攻撃者が制御した値を受け入れてしまう。

例: Apache Camel exec RCE (CVE-2025-27636)

脆弱なバージョンの Apache Camel では、Command Center ルートが信頼できないリクエストをブロックしようとして CamelExecCommandExecutableCamelExecCommandArgs のヘッダを削除していました。比較は equals() で行われていたため、正確に小文字で表記された名前のみが削除されていました。

# 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プロセスの権限でremote command executionが発生します。

検出と緩和

  • すべてのヘッダー名を単一のケース通常は小文字に正規化し、allow/denyの比較を行う前にこれを実施する。
  • 疑わしい重複を拒否する:Header:HeAdEr: の両方が存在する場合は異常として扱う。
  • positive allow-list を canonicalisation ので適用する。
  • 管理用エンドポイントを認証とネットワーク分割で保護する。

References

{{#include ../../banners/hacktricks-training.md}}