同一オリジンポリシーとは、あるオリジンから読み込まれた文書やスクリプトについて、そのリソースから他のオリジンのリソースにアクセスできないように制限するものです。同一オリジンポリシーはウェブのセキュリティにおける重要な仕組みであり、悪意ある行動を起こしかねないリソースの分離を目的としています。

オリジンの定義

2つのページにおいてプロトコルとポート番号(もしあれば)とホストが等しい場合、両者のページは同一のオリジンを持っていると見なされます。ここでは「スキーム/ホスト/ポート」の組み合わせで参照されます。

以下の表は、各行の 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/secure.html 不一致 プロトコルが異なる
http://store.company.com:81/dir/etc.html 不一致 ポート番号が異なる
http://news.company.com/dir/other.html 不一致 ホストが異なる

file: URL におけるオリジンの定義も参照してください。

オリジンの継承

about:blankjavascript: の URL のページから実行されたスクリプトは、その URL にオリジンのサーバーについての情報が明示的に含まれていないため、その URL を開いた文書のオリジンを継承します。例えば、 about:blank は (例えば Window.open() メカニズムを使用して) 新しい空のポップアップウィンドウを生成し、その中に親スクリプトがコンテンツを書き込むために使用されます。ポップアップウィンドウにもコードが含まれた場合、そのコードはそれを生成したスクリプトと同じオリジンを継承します。 data: の URL は新しく、空のセキュリティコンテキストを生成します。

補足: Gecko 6.0 以前のアドレスバーに入力された data URL は、その時点にブラウザーが表示していたページのセキュリティコンテキストを継承していました。

IE における例外事項

Internet Explorer には、同一オリジンポリシーについて2つ大きな例外があります。

  • 信頼済みゾーン: 双方のドメインが高く信頼されたゾーン(企業のドメインなど)である場合は、同一オリジンの制限が適用されません。
  • ポート: IE は同一オリジンの確認要素にポートを含みません。従って、http://company.com:81/index.html http://company.com/index.html は同一オリジンとみなされ、制限は適用されません。

これらの例外事項は非標準であり、 他のブラウザーでこのような挙動には対応していません。しかし、 Windows RT や IE ベースのウェブアプリケーションを開発する場合は役に立つかもしれません。

オリジンの変更

ページのオリジンは、いくつかの制限の下で変更されることがあります。スクリプトを用いると、 document.domain の値を現在のドメインまたは上位ドメインに変更できます。スクリプトによって現在のドメインの上位ドメインへオリジンが変更された場合、より短くなったドメイン名は次回のオリジン検査時に用いられます。例えば、 http://store.company.com/dir/other.html にあるドキュメント内のスクリプトが以下のコードを実行したと仮定します。

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 を含むどのような変更においても、ポートは null で上書きされます。従って、スクリプトの最初に document.domain = "company.com" を設定しただけでは、company.com:8080company.com とは互いにアクセスできません。双方のポートが null になるように、双方で設定しなければなりません。

注記: サブドメインから安全に親ドメインへアクセスさせるために document.domain を使用する際は、親ドメインとサブドメインの双方で同じ値を document.domain に設定することが必要です。この作業は、単に親ドメインを元の値に戻す際にも必要です。これを怠るとパーミッションエラーが発生するでしょう。

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

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

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

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

  • <script src="..."></script> による JavaScript。構文に関するエラーメッセージは、同一オリジンのスクリプトについてのみ読み取り可能です。
  • <link rel="stylesheet" href="..."> による CSS。CSS は緩い構文規則を持っているため、オリジンをまたぐ CSS には適切な Content-Type ヘッダを付加することが必要です。制約はブラウザーにより異なり、ブラウザーごとの詳細は IE日本語訳)、Firefox日本語訳)、ChromeSafari日本語訳) (CVE-2010-0051 までスクロールしてください)、Opera の各項目を参照してください。
  • <img> による画像。サポートされる画像形式は PNG、JPEG、GIF、BMP、SVG などです。
  • <video> および <audio> によるメディアファイル。
  • <object><embed> および <applet> によるプラグイン。
  • @font-face で指定されたフォント。異なるオリジンのフォントを許可するブラウザーもありますが、フォントにも同一オリジンを要求するブラウザーもあります。
  • <frame><iframe> に関連する様々なもの。このような手法を用いた際に異なるオリジンと通信できてしまうことを防ぐため、サイトに X-Frame-Options ヘッダを付加することができます。

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

異なるオリジンへのアクセスを許可するには、CORS を使用します。

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

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

異なるオリジンへスクリプトからアクセスできる API

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

window.postMessage を使用すると、異なるオリジンのドキュメント間における通信がさらに可能となります。

仕様書: https://html.spec.whatwg.org/multipage/browsers.html#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
属性  
URLUtils.href 書き込みのみ

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

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

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

Cookie におけるオリジンの定義は異なります。ページは自身のドメインまたは任意の親ドメイン(親ドメインが public suffix ではない場合に限る)用の Cookie を設定できます。 ドメインが public suffix であるかを判断する際、Firefox と Chrome は Public Suffix List を使用します。Internet Explorer は独自の方法で public suffix であるかを判断します。使用しているスキーム (http/https) やポートに関係なく、ブラウザーはサブドメインも含めて Cookie を使用可能にします。Cookie の設定時に Domain、Path、Secure、Http-Only フラグを用いることで、その Cookie の利用範囲を制限できます。Cookie を読み取るとき、Cookie を設定した場所から知ることはできません。安全な https 接続のみ使用していたとしても、参照している Cookie は安全でない接続を通じて設定された可能性があります。

関連情報

出典

  • 著者: Jesse Ruderman

ドキュメントのタグと貢献者

最終更新者: commis1059,