Same-Origin Policyについて改めて調べてみた
Same-Origin Policyについて改めて調べたので、頭の整理がてら、この記事にまとめた。
オリジン (Origin) とは何か
インターネット上でリソースにアクセスする際には、URLが用いられる。オリジンとは、そのURLにおける、スキーム (プロトコル)、ホスト (ドメイン)、ならびにポート番号の組み合わせを指す[1]。これら3つの要素が全て合致する場合に限り、別々のリソースがSame-Origin (同一のオリジン) に属するといえる。
例えば、http://example.com/1/index.html
とhttp://example.com/2/index.html
は、パスが異なるものの、スキーム・ホスト・ポート番号の3つは全て同一で代表的であるため、同一のオリジンに属する。
一方で、http://example.com/index.html
とhttps://example.com/index.html
のようにスキーム (プロトコル) が異なる場合や、http://example.com/index.html
とhttp://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