同一オリジンポリシーとCORSに再入門する
同一オリジンポリシーとCORSは、Web開発者であれば常識だと思うが、なんとなーくしか理解できていないので勉強がてらまとめてみた。
同一オリジンポリシー
同一オリジンポリシーとは
同一オリジンポリシー(same origin policy)とは、JavaScriptなどのクライアントスクリプトからサイトをまたがったアクセスを禁止するセキュリティ上の制限のこと。
Webブラウザのサンドボックスに用意された制限の一つ。
受動的攻撃を防止するための対策。
同一オリジンである条件
同一オリジンと判定される条件は以下の通り。
JavaScript以外のクロスドメインアクセス
JavaScript以外のブラウザ機能では、クロスドメインアクセスが許可されているものがある。
- frame要素とiframe要素
- img要素
- script要素
- CSS
- form要素のaction属性
- formの送信はJavaScriptから常に操作でき、この仕様を悪用した攻撃手法がCSRF攻撃。CSRF攻撃はユーザの意図しないformを送信させられる。
CORS
CORSとは
同一オリジンポリシーの制限を超えて、サイト間でデータやりとりしたいニーズに対応した仕様。
クロスオリジンでのデータアクセスを可能にしている。
シンプルなリクエスト
下記のシンプルなリクエストの条件を満たしているリクエストの場合、XMLHttpRequest
を用いて異なるオリジンにHTTPリクエストを送ることができる。
HTMLフォームから送られるリクエストを基準として、過度にリスクが増加しない範囲で条件が選択されている。
以下の条件をすべて満たすものを「シンプルなリクエスト」としている。
- メソッドは下記のうちいずれか
- GET
- HEAD
- POST
- XMLHttpRequestオブジェクトのsetRequestHeaderメソッドで設定するリクエストヘッダは以下に限る
- Accept
- Accept-Language
- Content-Language
- Content-Type
- Content-Typeヘッダは以下のいずれかであること
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
originの許可
ClientからServerへクロスオリジンリクエストのシーケンス
リクエスト
GET /resources/public-data/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Origin: https://foo.example
リクエストで送っているOriginで呼び出しが https://foo.example
から来たことを示している。
レスポンス
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2 Access-Control-Allow-Origin: https://foo.example Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml […XML データ…]
レスポンスでは、サーバーがAccess-Control-Allow-Originヘッダーを返信している。
https://foo.example
以外のドメインはすべて、サイト間の方法でリソースにアクセスすることができなくなっている。 Access-Control-Allow-Origin ヘッダーに、リクエストの Origin ヘッダーの中で送信された値を含めることでリソースへのアクセスを許可できる。
プリフライトリクエスト
クロスオリジンアクセスにおいて、「シンプルなリクエスト」の条件を満たさない場合、ブラウザはプリフライトリクエストというHTTPリクエストを送信する。
プリフライトリクエストは始めに OPTIONS メソッドによる HTTP リクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめるリクエスト。
プリフライトリクエストのシーケンス
要求に対するリクエストとレスポンスの対応表
要求の種類 | リクエスト | レスポンス |
---|---|---|
メソッドに対する許可 | Access-Control-Request-Method | Access-Control-Allow-Methods |
ヘッダに対する許可 | Access-Control-Request-Headers | Access-Control-Allow-Headers |
オリジンに対する許可 | Origin | Access-Control-Allow-Origin |
認証情報を含むリクエスト
XMLHttpRequestのプロパティ「withCredentials」で、クロスオリジンのajax通信で、リクエストにcookieなどの認証情報を含めるか否かを設定できます。デフォルトでは含まれない。
クロスオリジンで認証情報の送信を許可するためには、サーバー側で以下のようにヘッダーを返す必要がある。
Access-Control-Allow-Origin: https://syncer.jp Access-Control-Allow-Credentials: true