🕸

Same-Origin Policyについて改めて調べてみた

2021/10/18に公開

Same-Origin Policyについて改めて調べたので、頭の整理がてら、この記事にまとめた。

オリジン (Origin) とは何か

インターネット上でリソースにアクセスする際には、URLが用いられる。オリジンとは、そのURLにおける、スキーム (プロトコル)、ホスト (ドメイン)、ならびにポート番号の組み合わせを指す[1]。これら3つの要素が全て合致する場合に限り、別々のリソースがSame-Origin (同一のオリジン) に属するといえる。

例えば、http://example.com/1/index.htmlhttp://example.com/2/index.htmlは、パスが異なるものの、スキーム・ホスト・ポート番号の3つは全て同一で代表的であるため、同一のオリジンに属する。

一方で、http://example.com/index.htmlhttps://example.com/index.htmlのようにスキーム (プロトコル) が異なる場合や、http://example.com/index.htmlhttp://api.example.com/index.htmlのようにホスト (ドメイン) が異なる場合は、異なるオリジンに属する。

Same-Origin Policy とは何か

Same-Origin Policyは、セキュリティ上の制約であり、あるオリジンに属するリソース (ドキュメントやスクリプト) からの、異なるオリジンに属するリソースに対するアクセスを制限する[2]。

例えば、あるオリジン (https://www.example.comとする) から取得したHTMLに、<img src="https://api.example.com/user/1/delete">という<img>要素が含まれるとする[3]。すると、Webブラウザは、それが悪意のあるURLであっても気づかずに、https://api.example.com/user/1/deleteに対するリクエストを送信してしまう。このWebブラウザの性質を悪用すると、https://api.example.comを認証をすり抜けて、悪意のあるリクエストを送信することが可能となる。<img>要素に限らず、悪意のあるJavaScriptをリソースに含めれば、より多様な攻撃が可能である。

上述した攻撃手法は、Cross-Site Request Forgery (CSRF) と総称される。Same-Origin PolicyはCSRFを防止する上で、重要な対策の一つである。

異なるオリジンへのアクセスはどのように扱われるか

異なるオリジンに対するリクエストは、Same-Origin Policyに基づくと、以下の3種類に大別して扱われる[2,4]。

  • 異なるオリジンのリソースに対する書き込み (Cross-origin writes)。異なるリソースへのリンクやリダイレクトなどを指す。これらは、概してブラウザ上では許可される。例えば、異なるオリジンのリソースに対してリクエストを送信することは許可されるが、そのレスポンスを読むことは後述するCross-origin readsに該当するために禁止される (すなわち、writesは許可されることから、Same-Origin PolicyによってCSRFが完全に阻止されるわけではない[5])。
  • 異なるオリジンのリソースの埋め込み (Cross-origin embeds)。具体的には、以下のようなケースが存在する。これらは概して、ブラウザ上では許可される。
    • <script href='~'>により、スクリプトが読み込まれる場合
    • <link>により、CSSが適用される場合
    • <img>により画像が表示される場合
    • <video><audio>によりメディアファイルが再生される場合
    • <object><embed>によりリソースが埋め込まれる場合
    • <iframe>によってリソースが埋め込まれる場合 (なお、X-Frame-Optionsヘッダにより、異なるオリジンへの埋め込みを回避可能である)
  • 異なるオリジンのリソースの読み込み (Cross-origin reads)。例えば、fetch APIによって外部リソースを取得したいケースが該当する。これは、概してブラウザ上で禁止される。

一方で、fetch APIでバックエンドAPIにリクエストを行う場合など、Cross-origin readsを行いたいケースは、実際のところ多い。そこで、異なるオリジンのリソースへのアクセスを安全に取り扱うための方法として、Cross-Origin Resource Sharing (CORS) といった仕組みが存在する。CORSに関しては、別の記事にて詳述したい。

参考文献

[1] https://developer.mozilla.org/en-US/docs/Glossary/Origin
[2] https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
[3] https://developer.mozilla.org/en-US/docs/Glossary/CSRF
[4] https://ieftimov.com/post/deep-dive-cors-history-how-it-works-best-practices/
[5] https://medium.com/@jeanpan/what-is-cors-cross-origin-resource-sharing-9f0c463621c6

Discussion