はじめに
運用しているSPA(シングルページアプリケーション)を脆弱性診断ツールにかけたところ、CSRFに対する指摘を受けました。
SPAに対するCSRF対策の知識が薄かったので、改めてSPAでのCSRFリスク評価や対策の考え方を調査・検討した時の備忘録を残しておきます。
Cookie(Session)認証の場合 (MPAで広く採用)
まず前提として、広く知られているマルチページアプリケーションでのCSRF攻撃の流れをおさらいします。
- Cookie(Session)認証を採用している正規ウェブサイトにログイン
- ブラウザのCookieに正規サイトのセッションIDが保存される
- ユーザーが広告の誤クリックなどで罠サイト(trap.com)にリダイレクトしてしまう
- 罠サイトを開いた時に、正規サイトに向けたCSRF攻撃用スクリプトが発火する
- 正規サイトではリクエストを実行していないが罠サイト(trap.com)から実行される
- 罠サイトからのリクエスト時に、Cookieに保存されていたセッションIDが自動付与された状態で実行される
-
CSRF攻撃成立
ユーザー自身が正規サイトでリクエストを実行したわけではないにもかかわらず、罠サイトから発行されたリクエストが、ユーザーのセッションを利用して実行されてしまう
このような流れでCSRF攻撃が成立してしまうため、ページにCSRFトークンを埋め込んで検証するなどの対策が必要になります。(今回の記事ではスコープ外なので割愛)
トークン認証の場合 (SPAで広く採用)
次にシングルページアプリケーションでのCSRF攻撃の流れを確認します。
- トークン認証を採用している正規ウェブサイトにログイン
- ブラウザのlocalStorageまたはsessionStorageに正規サイトの認証トークンが保存される
Cookieには認証情報は保存されていない - ユーザーが広告の誤クリックなどで罠サイト(trap.com)
にリダイレクトしてしまう - 罠サイトを開いた時に、正規サイトに向けたCSRF攻撃用スクリプトが発火する
- 正規サイトではリクエストを実行していないが罠サイトから実行される
- 認証トークンはlocalStorageに保存されているため、罠サイトからのリクエストでは自動で含めることができない
-
CSRF攻撃不成立
罠サイトからリクエストは発行されるが、トークンを自動付与することはできないので認証エラーで実行は成立しない
※ localStorageに保存されたデータは同じオリジンのみアクセス可能なので、罠サイトの異なるオリジンから、正規サイトのlocalStorageに保存されたデータはアクセスすることができない
このような流れで罠サイトからは認証情報を得ることができないので、CSRF攻撃が成立しません。
なぜトークン認証を行なっているSPAでCSRF攻撃の指摘を受けたのか?
トークン認証を行う場合は基本的にCSRFの攻撃対象にならないが、なぜ今回は指摘されたのか?
指摘を受けたのは下記のリクエストです。
A. メールアドレスを元にアカウント有無を確認するリクエスト
B. 未ログイン時のレコード作成リクエスト
これらはどちらも未認証のAPIです。
確かに未認証APIは、誰でもアクセス可能なため、CSRF攻撃によって不正なリクエストが発生する可能性があります。
ここで指摘を受けていました。
では果たして未認証のAPIはCSRF対策を行うべきなのでしょうか?
下記はIPAからの引用です
今回の指摘対象にてCSRF攻撃は問題になるか?
A. メールアドレスを元にアカウント有無を確認するリクエスト
- 実行されたところで特に問題は起きない
B. 未ログイン時のレコード作成リクエスト
- 意図せずにレコードが作成される可能性あり
指摘を潰すために対策を導入すべきか
Aについて
- このAPIは、指定されたメールアドレスのユーザーが存在するかを確認するだけであり、システムへの影響は極めて限定的
- 仮にCSRF攻撃が行われたとしても、攻撃者が得られる情報は「ユーザーが存在するか?」に留まる
Bについて
- レコードが実際に作成される可能性はあるが、未認証のオープンAPIであることから、そもそも誰でもリクエストを送信できる仕様
- このAPIはパラメータが複雑で、正常リクエストを突き止めるのは困難である
- パラメータが適切でなければレコードが作成されない設計になっているため、不正リクエストが成功する可能性は低い
- CSRF対策ではなく、リクエスト形式を解析しようとするようなDoS攻撃に備えた対策をするべきではないか
結論
認証後のAPIが指摘対象となっている場合、もしくは認証なしのAPIでも掲示板などの匿名で誰でも見ることができる場所にレコード生成できるような公開APIが指摘対象となっている場合は、CSRF対策を講じるべきかと思います。
しかし今回指摘されたこれら未認証のAPIに対しては、CSRF攻撃の本質的な「ログインユーザーになりすまして重要なリクエストを実施する」というものに当てはまらないので、対応は不要と判断しました。
SPAにCSRF対策を講じる場合
認証が必要なAPI
- トークン認証なのでCSRF攻撃の対象外
認証なしのAPI
- CORSポリシーの最適化
-
application/json
の強制(単純リクエストでなくすることで、プリフライトリクエストを発生させてCORSポリシーで弾く) - 独自リクエストヘッダの強制(単純リクエストでなくすることで、プリフライトリクエストを発生させてCORSポリシーで弾く)
- CSRF対策以外に、リクエスト数を制限するレートリミットなどのDoS対策
参考