SameSite Cookies

XS-Search

October 1, 2020
Category Attack, Attack Principle
Defenses Fetch Metadata, SameSite Cookies

XS-Search(クロスサイトサーチ)は、XS-Leaksのファミリーの中で重要な攻撃原理です。 この種の攻撃は、クエリベースの検索システムを悪用し、攻撃者のオリジンからユーザー情報をリークさせます1 2。 元々の攻撃は、検索システムが結果を返すかどうかを検出するためにレスポンス時間を用いて、以下のように行います。 リクエストの結果がヒットした場合の時間(hit)と、結果がヒットしなかった場合の時間(miss)を計測する。 検索エンドポイントへのリクエストに対して、timing attackを開始し、最初の文字 (?q=r) をブルートフォースで攻撃する。 2.で計測した時間が1.で計測したhitである場合、もう一文字追加する (?q=ra); そうでなければ、新しい文字 (?q=s) を試す。 最終的に、完全なシークレット(?q=secret)を取得できる。 この攻撃は、正確さを期すために複数のタイミング測定が必要であり、インフレーション技術や統計分析によって改善することができます。 さらに、一文字ずつブルートフォースするのではなく、攻撃者は特定の単語や文章を検索して結果の出現箇所のみを漏洩させることができます。 この攻撃の最も重要な部分はその原理であり、様々なXS-Leaksに適用することが可能です。 レスポンス時間の増加方法 # XS-Searchのインフレーション技術は、2つのレスポンス(hitまたはmiss)を区別しやすくすることで攻撃の精度を上げるために使用されます。 以下の2つのメカニズムにより、攻撃者はより適切な計測を行うことができます。 検索システムが結果を返す際に、特定のGETパラメータをレスポンスに反映させるとレスポンスのサイズが大きくなる。これによりレスポンスをネットワーク上に送信する時間が大幅に増加するため、リクエストをより区別しやすくする。 レスポンスを返す前に、サーバーにさらに計算作業を実行させる。この方法は、より表現力の高いクエリー言語を提供する検索システムに適用できる。(例:Gmailのexclude termsは結果内のすべての文字を処理する) 拡張原理 # XS-Search に関するオリジナルの研究はタイミング攻撃に焦点を当てていましたが、この攻撃の原理は他の XS-Leak にも拡張することができます。 前述のように信頼性の低いタイミング測定に頼るのではなく、攻撃者は他の XS-Leak を利用して同じ情報を抽出することができます。 クエリベースの検索システムでは、ユーザーはクエリを送信し、そのクエリに関連するレスポンスを取得します。 この動作は、2つの異なる結果をもたらす可能性があります。 システムが結果を表示し、ページが特定の動作をする(第1の状態)。 システムが結果を表示せず、ページがステップ1とは異なる方法で動作する(第2の状態)。 上記の両方の挙動をタイミングよりも信頼性の高い XS-Leak で区別できる場合、攻撃者はより効率的な XS-Search 攻撃を行うことができます。 例えば、検索結果によってページのフレーム数が変化する(ステップ1と2が区別できる)場合、この攻撃原理は Frame Counting XS-Leak を適用することができるため、タイミング測定を使用するよりも正確である可能性があります。 対策 # Attack Alternative SameSite Cookies (Lax) COOP Framing Protections Isolation Policies XS-Search (timing) ✔️ ❌ ❌ RIP 🔗 NIP 🔗 – 異なるシナリオに対して有効な防御機構を組み合わせる必要があります ...

Window References

October 8, 2020
Abuse Window References
Category Attack
Defenses Fetch Metadata, SameSite Cookies, COOP

もしページが opener プロパティを null に設定したり、ユーザーの状態に応じて COOP による保護を使用している場合、その状態に関するクロスサイト情報を推測することができます。 例えば、攻撃者は認証されたユーザーのみがアクセスできる iframe (または新しいウィンドウ) でエンドポイントを開き、そのウィンドウの参照をチェックするだけで、ユーザーがログインしているかどうかを検出することができます。 コード # 以下のコードは、open プロパティが null に設定されているかどうか、あるいは COOP ヘッダーが unsafe-none 以外の値で存在するかどうかを検出する方法を示しています。 これは、iframeと新しいウィンドウの両方で行うことができます。 // 脆弱な攻撃対象URL const v_url = 'https://example.org/profile'; const exploit = (url, new_window) => { let win; if(new_window){ // 新しいタブを開き、win.opener が COOP の影響を受けたか、あるいは null に設定されたかどうかを確認 win = open(url); }else{ // opener が定義されているかどうかを検出するために iframe を作成 // COOP の検出や、ページがフレーム保護を実装している場合は機能しない document.body.insertAdjacentHTML('beforeend', '<iframe name="xsleaks">'); // iframeを脆弱な攻撃対象URLにリダイレクトする win = open(url, "xsleaks"); } // ページのロードを2秒待つ setTimeout(() => { // 新しく開いたウィンドウのオープナープロパティを確認する if(! ...

CORB Leaks

October 1, 2020
Abuse Browser Feature, Error Events, Content-Type, nosniff
Category Attack
Defenses Fetch Metadata, SameSite Cookies

Cross-Origin Read Blocking (CORB) は、Spectre などの投機的サイドチャネル攻撃の影響を軽減することを目的とした、Web プラットフォームのセキュリティ機能です。残念ながら、特定のタイプのリクエストをブロックすることで、あるリクエストではCORBが実行され、別のリクエストでは実行されなかったことを攻撃者が検出できる、新しいタイプのXS-Leaks 1 をもたらしました。とはいえ、このXS-Leaksは、CORBによって積極的に保護される問題(Spectreなど)よりもはるかに影響は少ないです。 info これはChromiumの既知の問題であり、未修正のままであるかもしれませんが、ChromiumベースのブラウザでデフォルトでSameSite Cookieが展開されることにより、その影響は大きく軽減されます。 CORB & Error Events # 攻撃者は、CORBがレスポンスからボディとヘッダーを取り除く結果となるステータス コード2xxで、レスポンスがCORB protectedContent-Type(およびnosniff)を返す場合、CORBの保護機能が強制的に実行されたことを観察することができます。この保護機能を検出すると、攻撃者はステータスコード (成功 もしくは エラー) と Content-Type (CORBで保護されているかどうか) の両方の組み合わせをリークさせることができます。これにより、以下の例に示すように、2つの可能な状態を区別することができます。 1番目の状態はリクエストがCORBによって保護され、2番目の状態では、クライアントエラー(404)となる。 1番目の状態はCORBによって保護され、2番目の状態では保護されない。 以下の手順で、最初の例の文脈でこの保護機能を悪用することができます。 攻撃者は、Content-Typeがtext/htmlでnosniff ヘッダーが設定された200 OKのレスポンスを返すリソースをscriptタグに、クロスオリジンリソースとして埋め込むこみます。 機密性の高いコンテンツが攻撃者のプロセスに入るのを防ぐため、CORBは元のレスポンスを空のレスポンスに置き換えます。 空のレスポンスは有効なJavaScriptであるため、onerror イベントは発生せず、onload が代わりに発生します。 攻撃者は、1.と同様に2番目のリクエスト(2番目の状態に対応)をトリガーし、200 OK 以外のものを返します。このとき、onerror イベントが発生します。 興味深い動作は、CORBがリクエストから有効なリソースを作成し、JavaScript以外を含む可能性がある(エラーを引き起こす)ことです。非CORB環境を考慮すると、1.と 4.の両方のリクエストがエラーを引き起こします。これは、これらの状況によって区別可能であるとしてXS-Leakを導入しています。 nosniffヘッダーの検出 # CORBは、リクエストに nosniff ヘッダーが存在する場合、攻撃者に検出されてしまう可能性があります。この問題は、CORBがこのヘッダーの存在と一部のスニッフィングアルゴリズムによってのみ強制的に実行されることに起因しています。以下の例では、2つの区別可能な状態を示しています。 CORBは、リソースがnosniffヘッダーと共にContent-Typeがtext/htmlで提供される場合、scriptとして認識されたリソースを埋め込んだ攻撃者ページを防止します。 リソースがnosniffを設定せず、CORBがページの Content-Typeを推測できない場合(text/htmlのまま)、コンテンツが有効なJavaScriptとして解析できないためSyntaxErrorが発生します。このエラーは、scriptタグが特定の条件下でのみエラーイベントをトリガーするため、window.onerror をリッスンすることで捕捉できます。 対策 # SameSite Cookies (Lax) COOP Framing Protections Isolation Policies ✔️ ❌ ❌ RIP 🔗 NIP 🔗 – 異なるシナリオに対して有効な防御機構を組み合わせる必要があります。 ...

CORP Leaks

October 1, 2020
Abuse Browser Feature
Category Attack
Defenses Fetch Metadata, SameSite Cookies

説明 # Cross-Origin Resource Policy (CORP) は、Webプラットフォームセキュリティ機能で、Webサイトが特定のリソースを他のオリジンから読み込むことを防止することができます。CORBがデフォルトで一部のクロスオリジン読み込みをブロックするのに対し、CORPはオプトインの防御であるため、この保護機能はCORBを補完するものです。残念ながら、CORBと同様に、アプリケーションがこの保護の使用を誤って設定すると、新しいXS-Leakをもたらす可能性があります。 CORPがユーザーデータに基づいて強制される場合、WebページはXS-Leakをもたらすことになります。ページ検索機能が、結果を表示するときはCORPを強制し、結果を返さないときは強制しないのであれば、攻撃者は2つのシナリオを区別することができます。これは、CORPによって保護されたページ/リソースがクロスオリジンでフェッチされるとエラーを返すために発生します。 対策 # アプリケーションは、CORPがすべてのアプリケーションリソース/エンドポイントに展開されていることを保証すれば、このXS-Leakを回避することができます。さらに、クロスサイトリクエストの無効化を可能にする一般的なセキュリティメカニズムも、この攻撃を防ぐのに役立ちます。 SameSite Cookies (Lax) COOP Framing Protections Isolation Policies ✔️ ❌ ❌ RIP 🔗 NIP 🔗 – 異なるシナリオに対して有効な防御機構を組み合わせる必要があります。

Error Events

October 1, 2020
Abuse Error Events, Status Code, nosniff, Content-Type
Category Attack
Defenses Fetch Metadata, SameSite Cookies

Webページがサーバにリクエストを発行すると(例:フェッチ、HTMLタグ)、サーバはこのリクエストを受信して処理します。 受信した際にサーバは与えられた条件に基づいて、リクエストが成功(例:200)すべきか失敗(例:404)すべきかを決定します。 レスポンスがエラーステータスを持つ場合、ページを処理するためにブラウザによってerror eventが発行されます。 これらのエラーは、例えばHTMLコンテンツを画像として埋め込もうとした時のようなパーサーの処理が失敗するケースにも対応しています。 たとえば、攻撃者は認証されたユーザだけが利用できるリソースにユーザがアクセスできるかどうかを確認することで、ユーザがサービスにログインしているかどうかを検出できます1。 このXS-Leakの影響はアプリケーションによって異なりますが、ユーザを非匿名化する高度な攻撃につながる可能性があります2。 エラーイベントは様々な HTMLタグからスローされる可能性があり、ブラウザによって動作が異なるものもあります 3。 例えば、読み込まれたリソースやHTMLタグ、特定のヘッダ(例えば nosniff や Content-Type )の存在、あるいはブラウザのデフォルトの保護機能の適用などによって動作が変わることがあります。 エラーイベントで情報をリークさせる原理は、さまざまなXS-Leakに抽象化して適用できます。 たとえば、Cache Probingの1つの手法では、特定の画像がブラウザによってキャッシュされたかどうかの検出にエラーイベントを使用しています。 コード # 以下のコードは、<script> タグを使用してエラーイベントを検出する方法を示しています。 function probeError(url) { let script = document.createElement('script'); script.src = url; script.onload = () => console.log('Onload event triggered'); script.onerror = () => console.log('Error event triggered'); document.head.appendChild(script); } // google.com/404 が HTTP 404 を返すため、スクリプトはエラーイベントを発生する probeError('https://google.com/404'); // google.com は HTTP 200 を返すので、スクリプトは onloadイベントをトリガーする probeError('https://google.com/'); 対策 # このXS-Leakの緩和策は、アプリケーションが特定のリソースをどのように処理するかによって異なる可能性があります。 一般的なアプローチとしては、可能な限り一貫した挙動を採用することです。 特定のシナリオでは、アプリケーションはSubresource Protectionsを使用して、攻撃者がURLを予測して攻撃を進行させることを防ぐことができます。 最後に、一般的なWebプラットフォームのセキュリティ機能を導入することで、アプリケーションの実装に大きな変更を加えることなく、このXS-Leakをより大幅に緩和することができます。 ...

Frame Counting

October 1, 2020
Abuse iframes
Category Attack
Defenses Fetch Metadata, SameSite Cookies, COOP, Framing Protections

ウィンドウの参照により、クロスオリジンのページが他のページのいくつかの属性にアクセスできます。 これらの参照は、iframeとwindow.openを使用または許可するときに利用可能となります。 この参照は、同一生成元ポリシーを尊重し続けるため、ウィンドウに関する(限定的な)情報を提供します。 アクセス可能な属性の1つは、ウィンドウ内のフレーム数を提供するwindow.lengthです。 この属性は、ページに関する貴重な情報を攻撃者に提供します。 Webサイトでは一般的にフレーム(またはiframes)を使用しますが、この選択は必ずしもセキュリティ上の問題を意味するわけではありません。 しかし、Webサイトがユーザの情報に応じてページのフレーム数を変更する場合があります。 例えば、GETパラメータと利用者のデータに応じてレイアウトを変えるようなページで起こりえます。 攻撃者は、異なるページで window.length の値を測定することにより、被害者に関する情報を推測することが可能かもしれません。 コード # 以下のコードは、クロスサイトのページにおけるフレーム数に関する情報にアクセスする方法を示しています。 // ウィンドウへの参照を取得する var win = window.open('https://example.org'); // ページが読み込まれるのを待つ setTimeout(() => { // 読み込まれたiframeの数を読み取る console.log("%d iframes detected", win.length); }, 2000); 攻撃の対策 # 場合によっては、異なるアプリケーション状態が同じ数のフレームを持つことで、攻撃者がそれらを区別できないようにすることができます。 ただし、ページの読み込み中にフレーム数を連続的に記録することで、攻撃者に情報をリークする可能性があるパターンを示す可能性もあります。 // ウィンドウへの参照を取得する var win = window.open("https://example.org"); var pattern = []; // ループ内で、60ms間隔でiframeの数を登録する var recorder = setInterval(() => { pattern.push(win.length) }, 60); // 6秒後にループを解除する setTimeout(() => { clearInterval(recorder); console.log("The pattern is: %s", pattern.join(', ')); }, 6 * 1000); 事例 # フレームカウント攻撃の例としては、以下のようなものがあります。 ...

Navigations

October 1, 2020
Abuse Downloads, History, CSP Violations, Redirects, window.open, window.stop, iframes
Category Attack
Defenses Fetch Metadata, SameSite Cookies, COOP, Framing Protections

クロスサイトのページで画面遷移がトリガーされたか(または、そうでないか)を検出することは攻撃者にとって有用です。例えば、ウェブサイトはユーザの状態に依存(#case-scenarios)して、あるエンドポイントで画面遷移をトリガーする可能性があります。 どのような画面遷移が発生したかを検出することで攻撃者以下の様なことが可能になります。 iframeを使用してonloadイベントがトリガーされた回数を数える。 ウィンドウへの参照を通じてアクセス可能なhistory.lengthの値をチェックする。この値は被害者のhistory.pushStateや通常の画面遷移によって変更された履歴の数を提供しています。攻撃者はhistory.lengthの値を取得するためにウィンドウへの参照のlocationをターゲットのウェブサイトに変更し、そしてSame-Originに戻すことによって最後に値を読み取ります。 ダウンロードトリガー # エンドポイントがContent-Disposition: attachment ヘッダを設定すると、ブラウザにレスポンスをナビゲートさせるのではなくファイルとしてダウンロードすることを指示します。この挙動が発生したかを検出すると、結果が被害者の状態に依存する場合に攻撃者に機密情報をリークできる可能性があります。 ダウンロードバー # Chromeベースのブラウザではファイルをダウンロードする際に、ブラウザのウィンドウ下部にダウンロードの進捗を示すバーがウィンドウと一体化して表示されます。攻撃者ウィンドウの高さを監視することでダウンロードバーが開いているかどうかを検出することができます。 // ウィンドウの現在の高さを読み取る var screenHeight = window.innerHeight; // ダウンロードのトリガーとなるページを読み込む window.open('https://example.org'); // タブの読み込みを待つ setTimeout(() => { // ダウンロードバーが表示された場合、すべてのタブの高さが小さくなります if (window.innerHeight < screenHeight) { console.log('Download bar detected'); } else { console.log('Download bar not detected'); } }, 2000); important この攻撃は、自動ダウンロード機能が有効になっているChromeベースのブラウザでのみ有効です。加えてこの攻撃はユーザがダウンロードばーばを能動的に閉じないと再検出できないため、繰り返し行うことはできません。 iframeを利用したダウンロード遷移 # Content-Disposition: attachment ヘッダをテストするもう一つの方法は遷移が発生したかどうかをチェックすることです。仮にページの読み込みによってダウンロードが発生した場合、遷移は発生せずウィンドウは同一オリジン内に留まります。 以下のコードは、そのような遷移が発生したかを検出しダウンロードが試行されたかを検出します。 // ダウンロード試行時のテスト先URLを設定する var url = 'https://example.org/'; // onloadイベントを計測するための外側のiframeを作成する var iframe = document.createElement('iframe'); document.body.appendChild(iframe); // ダウンロードの試行をテストするために、内側のiframeを作成 iframe.srcdoc = `<iframe src="${url}" ></iframe>`; iframe. ...

Network Timing

October 1, 2020
Abuse iframes
Category Attack
Defenses Fetch Metadata, SameSite Cookies, COOP, Framing Protections

ネットワーク タイミングのサイドチャネルは、ウェブが誕生したときから存在していました。これらの攻撃は、ブラウザがperformance.now()のような高精度のタイマーを出荷し始めたときに、新しい注目を集め、時とともに異なるレベルの影響を持つようになりました。 タイミング測定値を得るために、攻撃者は暗黙的または明示的なクロックを使用する必要があります。これらのクロックは、XS-Leaksの目的では通常交換可能であり、精度と利用可能性が異なるだけです。簡単のために、この記事では、すべてのモダンブラウザに存在する明示的なクロックであるperformance.now()APIを使用することを想定しています。 このサイドチャネルにより、攻撃者はクロスサイトリクエストが完了するまでにかかった時間から情報を推測することができます。ネットワークのタイミング測定は、ユーザーの状態によって変化する可能性があり、通常は下記の要素に連動します。 リソースサイズ バックエンドでの計算時間 サブリソースの数とサイズ キャッシュの状態. tip クロックの種類については、クロックの記事で詳しく説明しています。 モダンなWebのタイミング攻撃 # performance.now()は、リクエストの実行にかかる時間を測定するために使用できます。 // クロックを開始します。 var start = performance.now() // fetchリクエストが完了するまでの時間を計測します。 fetch('https://example.org', { mode: 'no-cors', credentials: 'include' }).then(() => { // fetch終了した時点で時間差を計算します。 var time = performance.now() - start; console.log("The request took %d ms.", time); }); Onloadイベント # 同じような処理で、リソースを取得するのにかかる時間を測定するには、単に onload イベントを監視することで可能です。 // 時間が欲しいページを指すscript要素を作成します。 var script = document.createElement('script'); script.src = "https://example.org"; document.body.appendChild(script); // クロックを開始します。 var start = performance.now(); // スクリプトがロードされたら、リクエストが完了するまでの時間を計算します。 script.onload = () => { var time = performance. ...

Performance API

October 1, 2020
Abuse window.performance
Category Attack
Defenses SameSite Cookies, CORB

Performance API # Performance APIは、Resource Timing APIのデータによって強化されたパフォーマンス関連の情報へのアクセスを提供します。このAPIは、持続時間のようなネットワークリクエストの時間情報を提供しますが、サーバーから送られたTiming-Allow-Origin: *ヘッダーがある場合、転送サイズとドメイン検索時間も提供されます。 このデータには、 performance.getEntriesまたはperformance.getEntriesByNameを使ってアクセスすることができます。また、performance.now()の差分を使って実行時間を取得することもできますが、これはミリ秒しか提供しないため、Chromeのfetchでは精度が低い可能性があります。 ネットワークのduration # リクエストのNetwork durationを performance API から取得することができます。 以下のスニペットはリクエストを実行し、200ms後に performance オブジェクトから持続時間を取得します。 async function getNetworkDuration(url) { let href = new URL(url).href; // duration = 0 のリクエストがあるため、fetch()の代わりに画像を使用する。 let image = new Image().src = href; // performance.getEntriesByName()に追加されるリクエストを待ちます。 await new Promise(r => setTimeout(r, 200)); // 最後に追加された時間を取得する let res = performance.getEntriesByName(href).pop(); console.log("Request duration: " + res.duration); return res.duration } await getNetworkDuration('https://example.org'); info 他のブラウザと異なり、Firefoxはミリ秒単位で測定値を提供します。 X-Frame-Optionsを検知する # 埋め込み内にページを表示する場合 (たとえば、X-Frame-Options ヘッダーのため)、Chrome の performance オブジェクトに追加されません。 ...

Cache Probing

Abuse window.open, Error Events, Cache, iframes, AbortController
Category Attack
Defenses SameSite Cookies, Vary: Sec-Fetch-Site, Subresource Protections

Cache Probingは、あるリソースがブラウザによってキャッシュされているかどうかを検知する手法です。そのコンセプトは、初期のWeb1から知られており、当初はタイミングの差異を検知することに基づいていました。 ユーザがWebサイトに訪れると、画像、スクリプト、そしてHTMLコンテンツなどの様々なリソースが取得され、それらは(特定の条件下で)ブラウザによってキャッシュされます。この最適化により、ブラウザはこれらのリソースを再度要求することなくディスクから提供するため、その後のナビゲーションが高速化されます。もし攻撃者がどのリソースがキャッシュされているかを検知できれば、この情報を基に、ユーザが特定のページにアクセスしたことがあるかどうかをリークできます。 Cache Probingのバリエーションとして、Error Eventsを悪用することにより、より正確でインパクトのある攻撃を実行することができます。 攻撃の原理 # 攻撃者は、あるユーザーがあるSNSを訪問したかどうかを知りたいと考えています。 そのSNSにアクセスすると、いくつかのサブリソースがキャッシュされます。 ユーザが、SNSが通常取得するリソースを取得する攻撃者のページを訪問する。 Network Timing XS-Leakの手法を用いて、攻撃者のページはキャッシュからの応答(つまりステップ1が起こった)とネットワークからの応答(つまりステップ1が起こらなかった)の違いを検出することができます。(応答がキャッシュからの場合、遅延は顕著に短くなります。) Error EventsによるCache Probing # Error Events2を利用したキャッシュプロービングは、より正確な攻撃を可能にします。このアプローチでは、時間の計測に頼らず、Error Eventsといくつかのサーバサイドの挙動を活用して、あるリソースがキャッシュされたかどうかを検出します。この攻撃は、以下のステップを必要とします。 ブラウザキャッシュからのリソースを無効化する。このステップは、攻撃が別の訪問で以前にキャッシュされたリソースを考慮しないことを確認するために必要です。 ユーザーの状態によって異なる項目がキャッシュされるようなリクエストを実行する。例えば、ユーザーがログインしている場合にのみ、特定の画像を含むページをロードする。このリクエストは、<link rel=prerender...で対象のウェブサイトに移動したり、iframeでウェブサイトを埋め込んだり、window.openで新しいウィンドウを開くことで発生させることができる。 サーバが拒否するようなリクエストを引き起こす。例えば、長大なRefererヘッダを含んでいて、サーバーがリクエストを拒否するような場合です。もし、ステップ2でリソースがキャッシュされていれば、このリクエストはエラーイベントを発生させることなく、成功します。 キャッシュの無効化 # キャッシュからのリソースを無効にするには、攻撃者はそのサブリソースを取得する際にサーバーがエラーを返すようにする必要があります。これを実現するには、いくつかの方法があります。 ブラウザによってリクエストが開始され、新しいコンテンツを受け取る前にAbortController.abort()で中止された cache:'reload'オプション付きのフェッチリクエスト 長大なRefererヘッダと 'cache':'reload'を持つリクエスト。ブラウザはこれを防ぐためにリファラの長さに上限を設けているので、これはうまくいかないかもしれません。 POSTリクエストに fetch no-cors を指定した場合。エラーが返されない場合でも、ブラウザがキャッシュを無効化することがあります。 Content-Type、Accept、Accept-Languageなど、サーバーを失敗させる可能性のあるリクエストヘッダ。(よりアプリケーションに依存します) その他のリクエストプロパティ これらの方法のいくつかは、しばしばブラウザのバグとみなされていそうです。(例: this bug). Origin ReflectionによるCORS error # Origin Reflectionは、グローバルにアクセス可能なリソースに、リクエストを初期化したオリジンを反映したAccess-Control-Allow-Origin(ACAO)ヘッダを付与する挙動のことです。これは、CORSの設定ミス3と考えることができ、ブラウザのキャッシュにリソースが存在するかどうかを検知するのに使用できます。 info 例えば、Flask frameworkにおいて、origin refrectionはデフォルトの動作になっています。 もし server.com にホストされているリソースが target.com からリクエストされた場合、オリジンはレスポンスヘッダに次のように反映されるでしょう。Access-Control-Allow-Origin: target.com といった具合です。リソースがキャッシュされている場合、この情報はリソースと一緒にブラウザのキャッシュに保存されます。これにより、もし attacker.com が同じリソースを取得しようとした場合、2つの可能性があります。 リソースがキャッシュにない場合:リソースは Access-Control-Allow-Origin: attacker.com ヘッダーとともにフェッチされ、保存される可能性があります。 リソースがすでにキャッシュにある:フェッチ試行はキャッシュからリソースをフェッチしようとするが、要求しているオリジンと ACAO ヘッダーの値の不一致によりCORSエラーが起こる。(target.comが期待されているが、実際に提供されたのはattacker.com 。)以下に、この脆弱性を悪用して被害者のブラウザのキャッシュ状態を推測するコード例を示します。 // この関数は、単にURLを受け取り、CORS モードでfetchします。 // fetchでエラーが発生した場合、attacker. ...