優れた機能のために「クロスオリジン分離」が必要な理由

公開日: 2020 年 5 月 4 日

COOP と COEP を使用してウェブサイトを「クロスオリジン分離」にするでは、COOP と COEP を使用して「クロスオリジン分離」状態にする方法について説明しました。この記事は、ブラウザで強力な機能を有効にするためにクロスオリジン分離が必要な理由を説明する補足記事です。

用語集

このドキュメントでは、名前が似ている用語や略語を多数使用しています。以下に、用語集をまとめました。

背景

ウェブは、ドキュメントとスクリプトが別のオリジンのリソースとやり取りする方法を制限するセキュリティ機能である同一オリジン ポリシーに基づいて構築されています。この原則により、ウェブサイトがクロスオリジン リソースにアクセスする方法が制限されます。たとえば、https://a.example のドキュメントが https://b.example でホストされているデータにアクセスできないようにします。

ただし、同一オリジン ポリシーには歴史的にいくつかの例外があります。どのウェブサイトでも次のことができます。

  • クロスオリジン iframe を埋め込む
  • 画像やスクリプトなどのクロスオリジン リソースを含める
  • DOM 参照を使用してクロスオリジン ダイアログ ウィンドウを開く

ウェブ コミュニティが厳格な同一オリジン ポリシーのメリットに気づいたときには、ウェブはすでにこれらの例外に依存していました。

このような緩い同一生成元ポリシーのセキュリティ上の副作用は、次の 2 つの方法で修正されました。

  • クロスオリジン リソース シェアリング(CORS)プロトコルにより、サーバーが特定オリジンとのリソースの共有を許可していることが保証されます。
  • デベロッパーは、下位互換性を維持しながら、クロスオリジン リソースへのスクリプトの直接アクセスを暗黙的に削除します。このようなクロスオリジン リソースは「不透明」リソースと呼ばれます。そのため、画像に CORS が適用されていない場合、CanvasRenderingContext2D を使用したクロスオリジン ピクセル操作は失敗します。

これらのポリシー決定はすべて、ブラウジング コンテキスト グループ内で行われます。

ブラウジング コンテキスト グループには、プライマリ サイトと埋め込みサイトのアセットが含まれます。

長い間、この組み合わせでブラウザの安全性を維持するのに十分であり、直接パッチを適用する必要があるエッジケース(JSON の脆弱性など)は限られていました。

この動作は Spectre で変更され、コードと同じブラウジング コンテキスト グループに読み込まれたデータは読み取り可能になる可能性があります。特定のオペレーションにかかる時間を測定することで、攻撃者は CPU キャッシュの内容、つまりプロセスのメモリの内容を推測できます。このような攻撃は、プラットフォームに存在する低粒度のタイマーで可能であり、明示的(performance.now() など)と暗黙的(SharedArrayBuffer など)の両方の高粒度タイマーで高速化できます。

evil.com がクロスオリジン画像を埋め込む場合、Spectre 攻撃を使用して埋め込み画像のピクセルデータを読み取ることができます。これにより、「不透明性」に依存する保護が無効になります。

Evil.com はメインのウェブサイトで、Spectre を使用して埋め込まれた b.example iframe と画像を攻撃します。

理想的には、すべてのクロスオリジン リクエストは、リソースを所有するサーバーによって審査されます。審査が行われなかった場合、データが悪意のあるユーザーのブラウジング コンテキスト グループに到達することはありません。これにより、データは Spectre 攻撃の対象外となります。これをクロスオリジン分離状態と呼びます。

埋め込みコードがクロスオリジン分離状態の場合、リクエスト元のサイトは危険性が低いと見なされます。これにより、リクエスト元のサイトは SharedArrayBufferperformance.measureUserAgentSpecificMemory()高解像度タイマーをより高い精度で使用できるようになり、Spectre 攻撃の可能性を防ぐことができます。この状態では、document.domain の変更も禁止されます。

クロスオリジンの埋め込みポリシー

クロスオリジン エンベダー ポリシー(COEP)は、CORP または CORS でドキュメントに明示的に権限を付与していないクロスオリジン リソースがドキュメントに読み込まれるのを防ぎます。この機能を使用すると、ドキュメントがこのようなリソースを読み込めないことを宣言できます。

CORP ポリシーにより、どの埋め込みアセットが許可され、どの埋め込みアセットが許可されないかを示す図。
親サイト a.example は、COEP ポリシーを require-corp に設定しました。a.exampleb.example から 3 つのアセットを埋め込もうとしていますが、成功したのは 2 つだけです。2 つの成功した埋め込みには、クロスオリジン CORP ポリシーを含む JavaScript ファイルと、CORS が許可された画像が含まれています。3 つ目のアセットは、アセットを同じオリジンにのみ埋め込むことを要求する CORP ポリシーを持つ動画です。そのため、この動画は a.example に読み込まれません。

このポリシーを有効にするには、次の HTTP ヘッダーをドキュメントに追加します。

Cross-Origin-Embedder-Policy: require-corp

COEP は require-corp の単一の値を受け取ります。これにより、ドキュメントが同じオリジンからのみリソースを読み込むか、別のオリジンから読み込み可能として明示的にマークされたリソースのみを読み込むというポリシーが適用されます。

リソースを別のオリジンから読み込むには、クロスオリジン リソース シェアリング(CORS)またはクロスオリジン リソース ポリシー(CORP)のいずれかをサポートする必要があります。

クロスオリジン リソース シェアリング

クロスオリジン リソースがクロスオリジン リソース シェアリング(CORS)をサポートしている場合は、crossorigin 属性を使用して、COEP によってブロックされることなくウェブページに読み込むことができます。

<img src="https://third-party.example.com/image.jpg" crossorigin>

たとえば、この画像リソースが CORS ヘッダーで提供される場合は、crossorigin 属性を使用して、リソースを取得するリクエストが CORS モードを使用するようにします。また、CORS ヘッダーを設定しない限り、画像が読み込まれないようにします。

同様に、fetch() メソッドを使用してクロスオリジン データを取得することもできます。サーバーが適切な HTTP ヘッダーで応答する限り、特別な処理は必要ありません。

クロスオリジン リソース ポリシー

クロスオリジン リソース ポリシー(CORP)は、元々、別のオリジンによるリソースの読み込みからリソースを保護するためのオプトインとして導入されました。COEP のコンテキストでは、CORP はリソースを読み込むことができるユーザーに関するリソース所有者のポリシーを指定できます。

Cross-Origin-Resource-Policy ヘッダーには次の 3 つの値を使用できます。

Cross-Origin-Resource-Policy: same-site

same-site とマークされたリソースは、同じサイトからのみ読み込むことができます。

Cross-Origin-Resource-Policy: same-origin

same-origin とマークされたリソースは、同じオリジンからのみ読み込むことができます。

Cross-Origin-Resource-Policy: cross-origin

cross-origin とマークされたリソースは、どのウェブサイトでも読み込むことができます。(この値は、COEP とともに CORP 仕様に追加されました)。

クロスオリジンのオープナー ポリシー

Cross Origin Opener Policy(COOP)を使用すると、ドキュメントを別のブラウジング コンテキスト グループに配置することで、最上位のウィンドウを他のドキュメントから分離できます。これにより、ドキュメントがトップレベル ウィンドウと直接やり取りできなくなります。たとえば、COOP を含むドキュメントでダイアログが開くと、その window.opener プロパティは null になります。オープナーの参照の .closed プロパティは true です。

a.example はダイアログで b.example を開けませんでした。

Cross-Origin-Opener-Policy ヘッダーには次の 3 つの値を使用できます。

Cross-Origin-Opener-Policy: same-origin

same-origin とマークされたドキュメントは、同じオリジンで明示的に same-origin とマークされたドキュメントと同じブラウジング コンテキスト グループを共有できます。

同じブラウジング コンテキスト グループ内の「同一オリジン」ポップアップを操作できるウィンドウを描いた図。ただし、ブラウジング コンテキスト グループ外の「同一オリジン」とラベル付けされたポップアップは操作できない。

Cross-Origin-Opener-Policy: same-origin-allow-popups

same-origin-allow-popups を含む最上位ドキュメントは、COOP を設定していないか、COOP を unsafe-none に設定して分離をオプトアウトしているポップアップへの参照を保持します。

COOP

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none はデフォルトであり、オープナー自体に same-origin の COOP がない限り、ドキュメントをオープナーのブラウジング コンテキスト グループに追加できます。

概要

精度が向上した SharedArrayBufferperformance.measureUserAgentSpecificMemory()高解像度タイマーなどの機能にアクセスするには、ドキュメントで値が require-corp の COEP と値が same-origin の COOP の両方を使用する必要があります。どちらか一方でも存在しない場合、ブラウザはこれらの強力な機能を安全に有効にするのに十分な分離を保証しません。self.crossOriginIsolatedtrue を返すかどうかを確認することで、ページの状況を判断できます。

実装方法については、COOP と COEP を使用してウェブサイトを「クロスオリジン分離」にするをご覧ください。

リソース