Cross-Origin
Resource Sharing
Ajax時代のCSRF対策
CSRFとは
• Cross-Site Request Forgeries
• 正規のフォーム等以外からのリクエストを送り、
データを不正に送受信すること
• 詳しくはWikipedia:クロスサイトリクエストフォージェ
リ
Ajaxとは
• Asynchronous JavaScript + XML
• 非同期でJavaScriptを用いて必要な情報をXML
で取得し、動的に画面を書き換える方法
• 現在はXML以外にJSON等も用いられる
• サーバで動的にページを生成するものではない
jQueryとは違うの
• jQueryはAjaxを使うためのフレームワークの一
つ
• 他にもGoogle Web ToolkitやSpry等がある
AjaxでのCSRF
• 通常のCSRFはサーバへリクエストを送ること
で、不正にページを書き換える攻撃手法
• Ajaxではサーバへリクエストを送ってページを
動的に生成することは基本的にない
AjaxでのCSRF
• クライアントサイドで動的にページ生成する際
に不正なデータを入れ込まれる
• 正規のページに似せて骨格をつくり、ページを
構成する各パーツを正規のサーバから取得する
ことで、ぱっと見では見分けがつかないページ
を生成することが可能となってしまう
対策
• 各ブラウザは、同一ドメインのリソースのみを
Ajaxに利用できるように制限
「Ajaxクロスドメイン制約」
「同一生成元ポリシー」
JSONP
• HTMLのscriptタグを用いて、外部ドメインからデー
タを持つスクリプトを取得、リソースとして利用する
方法
<script src= http://data.example.com/req?data=example-data >
• JSONPのデータは、基本的にどこからでもリクエス
トして取得できてしまう。
→ データ漏えいの危険性
リファラ検証
• JSONPの呼び出し元を検証することで、攻撃サ
イトへのデータ提供を阻止する
• 最近のパーソナルファイアウォール等は、
Refererを削除するものがある
→ リファラ検証が成り立たない
その他の危険
• データ内容はあくまでJavaScript
• 適切なエスケープを行わないとXSSを許容してし
まうおそれがある
CORS
• 別ドメインリソースを取得するときのW3C勧告
• Ajaxがリソースを取ろうとした時に、ブラウザ
内部で動作する → JavaScriptで制御できない
使われるヘッダ
• Origin : データ参照元ドメイン
• Access-Control-* : 各種許可情報のやりとりに
使われる(ヘッダ名で内容は判断できる・後述
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページのドメ
イン情報等を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページのドメ
イン情報等を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
Ajaxの外部リソース取得
• XMLHttpRequest(XHR)の呼び出し
• JavaScriptからブラウザへリソースの要求が行われる
• ブラウザが外部ドメインかどうかを判断する
• ブラウザがpreflightリクエストが必要かを判断
する
preflightの条件
• HTTPメソッドがGET, POST, HEADのいずれか
• HTTPヘッダにAccept, Accept-Language,
Content-Language, Content-Type以外のフィー
ルドが含まれない
• Content-Typeの値はapplication/x-www-form-
urlencoded, multipart/form-data, text/plain
のいずれか
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページの情報
を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページの情報
を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
preflight - 送信
• OPTIONSメソッドを使用
• Originヘッダ
• 参照元スキーマ及びドメイン情報
• Access-Control-Request-Methodヘッダ
• リクエストに使用するメソッド
preflight - 送信
OPTIONS / HTTP/1.1
Host : data.example.com
Origin : http://www.example.com
Access-Control-Request-Method : GET
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページの情報
を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページの情報
を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
preflight - 受信
• 200番台のレスポンスコード
• Access-Control-Allow-Originヘッダ
• 許可されたOriginの情報(通常、リクエストと同値が返される)
• Access-Control-Max-Ageヘッダ
• preflightのTTL(秒単位
• Access-Control-Allow-Methodsヘッダ
• 許可するメソッドの一覧
• Varyヘッダ
• 内容によって応答が変更されるヘッダ一覧
preflight - 受信
HTTP/1.1 200 OK
Server: nginx/1.7.10
Date: Mon, 29 Jun 2015 09:52:05 GMT
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers,
Access-Control-Request-Method
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページの情報
を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
CORSシーケンス
• Ajaxで別ドメインのリソースを取得しようとする
• ブラウザがリソースに対して表示中ページの情報
を送る
• リソース側で許可されたアクセスかを判断し、ブ
ラウザに応答する
• 許可されたアクセスであれば、Ajaxの通信をブラ
ウザがリソースへ送信する
その他ヘッダ
• Access-Control-Allow-Credentials
• Cookieを許可するか
• Access-Control-Expose-Headers
• 使用可能なヘッダの一覧
前提条件
• DNS Spoofingがされていないこと
質疑応答

Cross-Origin Resource Sharing