同一オリジンポリシー

  1. Referer ヘッダーのプライバシーとセキュリティの考慮事項
  2. サブドメインテイクオーバー
  3. サブリソース完全性
  4. トランスポート層セキュリティ
  5. ユーザーによる有効化によって制御される機能
  6. 保護されたコンテキスト
    1. 保護されたコンテキストに制限されている機能
  7. 同一オリジンポリシー
  8. 安全でないパスワード
  9. 実践的なセキュリティ実装ガイド
    1. フォームの自動補完を無効にするには
  10. 攻撃
    1. Clickjacking
  11. 混在コンテンツ
  12. 無信頼の iframe Experimental
  13. 脆弱な署名アルゴリズム
  14. 証明書の透明性

同一オリジンポリシーは重要なセキュリティの仕組みであり、あるオリジンによって読み込まれた文書やスクリプトが、他のオリジンにあるリソースにアクセスできる方法を制限するものです。

これにより、悪意のある可能性のあるドキュメントを隔離し、起こりうる攻撃のベクターを減らすことができます。例えば、インターネット上の悪意のあるウェブサイトがブラウザー内で JS を実行して、(ユーザーがサインインしている)サードパーティのウェブメールサービスや (公開 IP アドレスを持たないことで攻撃者の直接アクセスから保護されている) 企業のイントラネットからデータを読み取り、そのデータを攻撃者に中継することを防ぎます。

オリジンの定義

二つのページのプロトコルポート番号 (もしあれば)、ホストが等しい場合、両者のページは同じオリジンです。これは「スキーム/ホスト/ポート番号のタプル」または時に単に「タプル」として参照されます (「タプル」は共に全体を構成する三つの部分の組み合わせを表します)。

以下の表は、各行の URL が http://store.company.com/dir/page.html と同じオリジンであるかを比較したものです。

URL 結果 理由
http://store.company.com/dir2/other.html 同一オリジン パスだけが異なる
http://store.company.com/dir/inner/another.html 同一オリジン パスだけが異なる
https://store.company.com/page.html 不一致 プロトコルが異なる
http://store.company.com:81/dir/page.html 不一致 ポート番号が異なる (http:// は既定で 80 番ポート)
http://news.company.com/dir/page.html 不一致 ホストが異なる

オリジンの継承

about:blankjavascript: の URL のページから実行されたスクリプトは、その URL にオリジンのサーバーについての情報が明示的に含まれていないため、その URL を開いた文書のオリジンを継承します。

例えば、 about:blank は (例えば Window.open() メカニズムを使用して) 新しい空のポップアップウィンドウを生成し、その中に親スクリプトがコンテンツを書き込むために使用されます。ポップアップウィンドウにもコードが含まれた場合、そのコードはそれを生成したスクリプトと同じオリジンを継承します。

data: の URL は新しく、空のセキュリティコンテキストを生成します。

ファイルのオリジン

現行のブラウザーでは、 file:/// スキームを使用して読み込まれたファイルのオリジンは、通常、不透明なオリジンとして扱われます。 つまり、ファイルが同じフォルダー内にある他のファイルを記載している場合(例えば)、それらは同じオリジンから来ているとはみなされず、 CORS エラーが発生する可能性があります。

URL 仕様書では、ファイルのオリジンは実装依存の状態であると規定されており、たとえセキュリティ上の影響が存在するとしても、一部のブラウザーでは同じディレクトリーまたはサブディレクトリーにあるファイルを同一オリジンとして扱うことができることに注意してください。

オリジンの変更

警告: ここで説明している (Document.domain セッターを使用する) 方法は非推奨です。同一オリジンポリシーによるセキュリティ保護を弱め、ブラウザーのオリジンモデルを複雑にして、相互運用性の問題やセキュリティバグを引き起こすためです。

ページのオリジンは、いくつかの制限の下で変更されることがあります。スクリプトを用いると、 Document.domain の値を現在のドメインまたは上位ドメインに変更できます。スクリプトによって現在のドメインの上位ドメインへオリジンが変更された場合、より短くなったドメイン名は次回のオリジン検査時に用いられます。

例えば、 http://store.company.com/dir/other.html にあるドキュメント内のスクリプトが以下のコードを実行したと仮定します。

js
document.domain = "company.com";

このコードが実行された後、そのページは http://company.com/dir/page.html におけるオリジンの検査を通過できます(許可を明示するために http://company.com/dir/page.html が自身の document.domain"company.com" に変更したと仮定します。詳しくは Document.domain を参照してください)。しかし、 company.com が自身の document.domainothercompany.com に変更することはできません。なぜなら company.com の上位ドメインではないためです。

ブラウザーはポート番号を個別に検査します。 document.domain を呼び出すと、 document.domain = document.domain の場合も含め、ポート番号が null で上書きされます。従って、スクリプトの最初に document.domain = "company.com" を設定しただけでは、 company.com:8080company.com とは互いにアクセスできません。双方のポートが null になるように、双方で設定しなければなりません。

この仕組みにはいくつかの制限があります。例えば、 document-domainPermissions-Policy が有効になっている場合や、文書がサンドボックス化された <iframe> 内にある場合は、 SecurityErrorDOMException が発生します。また、この方法でオリジンを変更しても、多くの Web API (localStorage, indexedDB, BroadcastChannel, SharedWorker など) で使用されているオリジンチェックには影響しません。失敗事例のより詳細なリストは、 Document.domain > Failures にあります。

メモ: サブドメインから親ドメインへアクセスさせるために document.domain を使用する際は、親ドメインとサブドメインの双方で同じ値を document.domain に設定することが必要です。この作業は、親ドメインを元の値に戻す際にも必要です。これを怠ると権限エラーが発生します。

異なるオリジンへのネットワークアクセス

XMLHttpRequest<img> 要素を使用する場合など、 同一オリジンポリシーは 2 つのオリジン間における通信を制御します。一般にこれらの通信は 3 つのカテゴリーに分類されます。

  • 異なるオリジンへの書き込みは、概して許可されます。例えばリンクやリダイレクト、フォームの送信などがあります。まれに使用される HTTP リクエストの際はプリフライトが必要です。
  • 異なるオリジンの埋め込みは、概して許可されます。例は後述します。
  • 異なるオリジンからの読み込みは一般に許可されませんが、埋め込みによって読み取り権限がしばしば漏れてしまいます。例えば埋め込み画像の幅や高さ、埋め込みスクリプトの動作内容、あるいは埋め込みリソースでアクセス可能なものを読み取ることができます。

以下に挙げるのは、異なるオリジンに埋め込むことができるリソースの例です。

  • JavaScript を <script src="…"></script> で使用する場合。構文に関するエラーメッセージは、同一オリジンのスクリプトについてのみ読み取り可能です。
  • CSS を <link rel="stylesheet" href="…"> で使用する場合。CSS は緩い構文規則を持っているため、オリジンをまたく CSS には正しい Content-Type ヘッダーが必要です。 MIME タイプが正しくなく、リソースが有効な CSS 構造で始まっていない場合、オリジン間読み込みであるこのスタイルシートの読み込みはブラウザーによってブロックされます。
  • <img> で表示された画像。
  • <video> および <audio> で再生されたメディア。
  • <object> または <embed> で埋め込まれた外部リソース。
  • @font-face が適用されたフォント。異なるオリジンのフォントを許容するブラウザーもありますが、同一オリジンを要求するものもあります。
  • <iframe> に関連するあらゆること。このような形のオリジン間のやりとりを防ぐため、サイトに X-Frame-Options ヘッダーを使用することができます。

異なるオリジンへのアクセスを許可する方法

異なるオリジンへのアクセスを許可するには、 CORS を使用してください。 CORS は HTTP の一部で、ブラウザーがコンテンツの読み込みを許可する他のホストをサーバーが指定できるようにするものです。

異なるオリジンへのアクセスをブロックする方法

  • 異なるオリジンへの書き込みを防ぐには、リクエスト内の Cross-Site Request Forgery (CSRF) トークンと呼ばれる推測できないトークンをチェックしてください。このトークンを知っているページのオリジンをまたがった読み込みを防ぎます。
  • 異なるオリジンからのリソースの読み込みを防ぐには、そのリソースが埋め込まれないようにします。リソースの埋め込まれると情報が漏えいする場合があるため、多くの場合は埋め込みの抑止が必要になります。
  • 異なるオリジンによる埋め込みを防ぐには、リソースの形式が先ほど述べたような埋め込み可能な形式だと思われないようにします。ほとんどの場合、ブラウザーは Content-Type を尊重しません。例えば <script> タグで HTML 文書を指した場合、ブラウザーは HTML を JavaScript としてパースしようとします。リソースがサイトの入口ではない場合は、埋め込みを抑止するため CSRF トークンも使用するとよいでしょう。

異なるオリジンへのスクリプトからの API によるアクセス

iframe.contentWindow, Window.parent, Window.open, Window.opener といった JavaScript API を用いると、ドキュメントが直接互いに参照することができます。2 つのドキュメントが同一のオリジンではない場合、 Window オブジェクトや Location オブジェクトなど、限られたオブジェクトにのみアクセスすることができます。詳しくは次の 2 つのセクションで説明します。

Window.postMessage を使用すると、異なるオリジンの文書間における通信がさらに可能となります。

仕様書: HTML Living Standard § Cross-origin objects.

Window

以下に示した Window のプロパティは、異なるオリジンからのアクセスが許可されています。

メソッド
Window.blur
Window.close
Window.focus
Window.postMessage
属性
Window.closed 読み取り専用
Window.frames 読み取り専用
Window.length 読み取り専用
Window.location 読み取り/書き込み
Window.opener 読み取り専用
Window.parent 読み取り専用
Window.self 読み取り専用
Window.top 読み取り専用
Window.window 読み取り専用

一部のブラウザーでは、仕様書で定められたものより多くのプロパティでアクセスが許可されています。

Location

以下に示した Location のプロパティは、異なるオリジンからのアクセスが許可されています。

メソッド
Location.replace
属性
Location.href 書き込みのみ

一部のブラウザーでは、仕様書で定められたものより多くのプロパティでアクセスが許可されています。

オリジンをまたいだデータストレージアクセス

ウェブストレージIndexedDB など、ブラウザー内部に保存されるデータへのアクセスは、オリジンによって権限が分かれています。それぞれのオリジンが個別にストレージを持ち、あるオリジンの JavaScript から別のオリジンに属するストレージを読み書きすることはできません。

Cookie におけるオリジンの定義は異なります。ページは自身のドメインまたは任意の親ドメイン (親ドメインが public suffix ではない場合に限る) 用の Cookie を設定できます。 ドメインが public suffix であるかを判断する際、Firefox と Chrome は Public Suffix List を使用します。Cookie の設定時に Domain, Path, Secure, HttpOnly の各フラグを用いることで、その Cookie の利用範囲を制限できます。Cookie を読み取るとき、Cookie を設定した場所から知ることはできません。安全な https 接続のみ使用していたとしても、参照している Cookie は安全でない接続を通じて設定された可能性があります。

関連情報