cross-origin resource sharing
TRANSCRIPT
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がされていないこと
質疑応答