CSRF基礎(Double Submit Cookie Pattern)[3/3]
イントロ
Webアプリを開発する際にセキュリティ対策は年々重要になっています。
対策すべき攻撃手法としてCSRF(クロスサイトリクエストフォージェリ)というものがあります。
第1回はその攻撃のメカニズムを説明しました。
そして、このCSRF攻撃には、対策手法が下記2種類あります。
第2回では「Synchronizer Token Pattern」で解説しました。
今回は第3回目で「Double Submit Cookie Pattern」について解説したいと思います。
対策手法
こちらも、第1、2回同様シーケンス図にしました。
第1回、第2回をベースに説明しますので、ぜひ第1回から読んでから以降をお読みください。Synchronizer Token Patternと比較しながら解説しますので第2回は必読!
基本的な考え方はSynchronizer Token Patternと同じです。CSRF Tokenをユーザー側に保存し、リクエスト時にBodyやHeaderに付与し、本物アマゾンはそのCSRF Tokenを比較検証し、攻撃されているかを見分けます。両者の違いはこの比較検証時に使用するCSRF Tokenの保存場所です。Synchronizer Token Patternでは本物アマゾンのサーバー側(Session)に保存します。対照的にDouble Submit Cookie Patternはユーザー側(Cookie)に保存します。そして本物Amazonへ購入リクエストを送る際[シーケンス図(3)]、CSRF TokenをCookieとそれ以外(Body、Header)の二箇所に格納して送ります(これがDouble Submit Cookie Patternの名前の由来、たぶん)。そして、本物アマゾンでは、Cookieに格納されているCSRF Tokenとそれ以外(Body、Header)に格納されたCSRF Tokenを比較検証し一致していれば、正規のリクエストと判断し処理を実行します。
Double Submit Cookie Patternの最大のメリットはサーバー側でCSRFトークンを保持しないことでしょう。でも、Session IDは保持してるやん!と思う方がいらっしゃるかもしれません。最近はSession IDをJWT形式でCookieに保存するやり方も存在しており、CSRF Tokenもクライアント側で管理する方法に需要があるのだと思います(過去記事を書いているので、興味があればご覧ください。)
本当に対策できているか考察
前回同様、Double Submit Cookie Patternに穴がないか見ていきましょう。
特に検証時の答えとなるCSRF TokenをCookieなんかに保存してしまっていても良いの?そもそもCSRFってCookieの仕組みを悪用したものではないの?と思っている方は多いと思います(最初は私もそうでした)。
結論から言うと、大丈夫です。ただし、Cookieが上書きされる脆弱性がなければ(後述)。ブラウザは送信の宛先が本物アマゾンであれば、それが偽アマゾンの画面からのリクエストでもCookieを付与してしまいます。しかし、Cookieの設定(HttpOnly属性、SameSite属性)をしっかり設定しておけば、攻撃者は偽アマゾンの画面を使ってCookieを書き換えることはできないのです。このため、いくら攻撃者が保有している本物アマゾンで生成されたCSRF Tokenを偽アマゾンに埋め込まれ、BodyやHeaderのCSRF Tokenを書き換えることができても、攻撃対象(Aさん)のCookieに格納されているCSRF Tokenは書き換えることはできません。
ここまで、Cookieが上書きされる脆弱性がないことを前提に話してきました。当然この脆弱性があると、Double Submit Cookie Patternは崩壊し、突破されてしまいます。では「Cookieが上書きされる脆弱性」とはどのようなものがあるのでしょうか?こちらはすでにセキュリティ界の巨人、徳丸先生が解説してくれています。
Double Submit Cookie Patternを使う場合、上記の脆弱性がないことが条件になると思います(そもそもあってはいけないですが)。
OWASPでは署名付きDouble Submit Cookie Patternを推奨
最後にOWASP Cheat Sheet Seriesでは、Cookieに保存する際にCSRF Tokenの署名つけることを推奨しています。署名とはCSRF Tokenを発行する際に、サーバー側に秘匿して保存されているシークレットキーを使ってハッシュ化して、そのハッシュ化された文字列と元のCSRF Token文字列を結合して送ると言うことです。これにより、いくら元のCSRF Tokenを攻撃者が改竄してもハッシュ値はシークレットキーがなければ作れませんので、改竄を検知できると言う仕組みです。しかし、署名をつけても上記の「Cookieが上書きされる脆弱性」があるとDouble Submit Cookie Patternは破綻しますので、しっかり対策しましょう!
最後に
全3回にわたって、CSRFについて解説してきました。ここまで読んでくれた方ありがとうございます!
なぜいきなり、CSRFについて解説したかというと、なんとAuth.js(NextAuth.js)のCSRF対策でDouble Submit Cookie Patternが利用されいているからなんです。次回はAuth.js(NextAuth.js)のソースを見ながらDouble Submit Cookie Patternが実際にどのように実装されているかを見てきたいと思います。気になる方はぜひフォローしてお待ちください!