SPA CSRF 対策
2021/07/25, last updated 2022/08/03 - moriya - ~2 Minutes
WEB アプリケーションのセキュリティでは、 CSRF に関しては重要性が理解されず、インパクトも大きいように思える。
ここ数ヶ月、いくつか SPA (Single Page Application) 関連のプロジェクトに 関わったのであるが、バックエンドに Laravel などの CSRF 対策が組込まれた フレームワークを導入すると CSRF エラーが頻発した。 GET/POST で駆動する従来型の WEB サーバとは考え方が違うのだろうか。
ブログ等を読んでも、Origin チェックだけで十分だとか、Origin チェックでは不十分だとか、 また、CORS でガードできるとか、できないとか、 非常に読んでいて混乱してしまう。
整理された情報が無いのか調べたところ、以下の情報が有用ではないかと思う。 owasp.org からの情報なので、信頼性もあるだろう。
このサイトで推奨しているのは、基本的には、Token(いわゆる csrf token) を使った方法であるようだ。 SPA の場合には、 JavaScript Guidance for Auto-inclusion of CSRF tokens as an AJAX Request header が参考になるだろう。要は、meta ヘッダか、DOM に CSRF token を置いて、その情報を XHR (XMLHttpRequest) にセットするという方法。
Origin のチェック、独自のリクエストヘッダの付与などについても記載されているが注意事項も記載されている。
Source Origin のチェックを行う場合、Origin ヘッダをチェック。マッチングパターンに注意すること。 無ければ、Referer ヘッダをチェック。IE11 で window.onload 時に form を post してみたが、 Origin は付かないようだ。Referer は付く。 Target Origin のチェックは思ったほど簡単ではないことについても記載されている。 Source Origin == Target Origin でなければ受けつけない、ということだが、 単純な SPA アプリだと、Source Origin == 自サーバーかどうか、というチェックになるだろうか。
CORS によるガードは、XHR を使う場合はチェックされるが、form でも情報が更新できる作り、 例えば、ログイン後、セッション ID を cookie に保存させ、 form を XHR で POST して情報を更新する、といった作りだと、 XHR 経由でなく、form 経由でも情報を更新させることができるので、 CORS のガードが効かないこともあるかもしれない。
Origin や CORS などによる抜けを防ごうとするためには、SPA でもやはり Token による対策が有効であろう。