はじめに
おはこんばんにちは。キティちゃんです。徐々に暑さが増していき、外へ出ると汗でべとべとになってしまう時期が来ましたね。そんな時期ですが、私は好きです。ですが、暑さで食欲が落ちるのは悩みですね。そんなことはさておき、今回はCSRFのことについて書いてみようと思います。
CSRFって?
CSRFとはクロス・サイト・リクエスト・フォージェリ(以降、CSRF(シーサーフ))の略で、あるサイト(例:ECサイトなど)にログインしているユーザAに対して、攻撃者Bが用意したページに何らかの方法で誘導し、ユーザAに強制的にサイト内でリクエストを送信させ処理を実行させる攻撃となります。もっと簡単に言ってしまえば、ユーザAに意図していない操作をさせることですね。
CSRFの何が問題なのか
例えばですが昔、掲示板にユーザが意図していない犯行予告の投稿がされてしまうといった事件がありました。このサイトはCSRFの対策を施していなかったことがきっかけで意図しない投稿が成功してしまうというものでした。
このように、CSRFの対策が取れていない場合、意図しない掲示板への投稿であったり、ECサイトなどであれば、ユーザの個人情報(パスワードやメールアドレスなど)が書き換えられてしまい、アカウントを乗っ取られる可能性が高まります。
どのように対策をすれば良いのか
大きく分けて2つのパターンがあります。
1つ目、CSRFトークン(以降、トークン)を用いる方法です。掲示板であれば、投稿前の確認画面、ECサイトなどであれば購入確認画面にてサーバ側でトークンを発行し、ユーザーは投稿または購入のボタンを押した際に、発行されたトークンを一つのパラメータとして入力したパラメータと一緒にリクエストを送信します。このトークンは画面上では分かりませんし、攻撃者もどんな値が発行されたかを知る方法がありません。なので、有効な対策方法の1つとして挙げられます。
ただし、トークンの値が攻撃者が推測しやすい値(極端な例ですが、今日の日付など)が発行される場合はあまり意味をなさないこともあります。なので、トークンを利用する場合は攻撃者が推測しにくい値を発行する必要があります。PHPであればopenssl_random_pseudo_bytes関数やrandom_bytes関数を使うのが無難だと思います。
2つ目、ヘッダにトークンの役割を果たすものを設定することです。X-CSRF-TOKENヘッダにトークンの値を付けるパターンとX-Requested-Withヘッダを付与するパターン(最近知ったので、まだ色々調べ中、、)があります。
・・・
他にも、Refererヘッダをチェックしたり、パスワード変更機能であれば、旧パスワード(=現在使用しているパスワード)を入力させることで、トークンのような役割を果たさせる方法もあります。ただ、Refererヘッダで対策しているところはあまり見ないですね。
実装時の注意点
2パターンの対策方法を記載しましたが、いずれもサーバ側にて値を検証する必要があります。サーバ側にて検証していない場合、トークンがあってないようなものとなってしまうので、攻撃者の餌食になります。ですので、トークンを発行する処理を実装するだけではなく、サーバ側で発行されたトークンなのかを検証する処理も併せて実装しましょう。
・・・
口で説明するのは簡単ですが、じゃあトークンが役割を果たしているかどうかというのはどうやって検証すればいいの?と思うかもしれません。診断企業では専用のツールを使用できるので比較的楽に検証ができるのですが、開発チームだと診断企業が利用しているようなツールは会社的にダウンロード対象ではないと思うので、検証は容易ではないと思われます。なので、申し訳ないのですが設計の段階からセキュア開発を心がけ、コードレビューをしっかりしましょうとしか言えません。予算があれば、脆弱性診断を依頼するのもありです(宣伝じゃありません)。
診断ではどういう観点でトークンをみるのか(小話もあるよ)
よくあるのが、トークンの値を削除、トークンの値を一部改ざん、過去に発行されたトークンが使用できないようになっているか、他のユーザで発行されたトークンが使用できないかですかね。重要視しているのは、サーバで発行された値がちゃんと検証されているのか、また、発行されたトークンは発行したユーザのセッションと紐づいているかという点を見ていたりします。
・・・
私もWeb診断をしている企業を何社か経験したのですが、トークンの評価の仕方は、全社異なっていました。一番厳しく見ていたところは、確定処理の二つ前の画面からワンタイムのトークンを発行していて、なおかつサーバ側でトークンの値をチェックしていることがCSRFの問題がないと評価していました。ECサイトで言えば、商品選択画面→カート画面→購入確認画面→商品購入確定画面という処理がある場合、カート画面に遷移した時点でサーバ側でトークンを発行し、商品購入確定画面までに2回のトークンチェックの処理が必要ということになります。1回しかトークンのチェックをしていない場合は危険度のレベルを変えて指摘していたと記憶しています(何年も前の話なので許してください)。
・・・
なので、診断を依頼した会社によって指摘の度合いも変わるので、アプリケーションのセキュリティ対策も診断会社に依存しそうだなぁっていつも思います。
まとめ
CSRF対策を怠ると意外と面倒なことになったりします。掲示板の事件も誤認逮捕に至っているのでね。。
まとめを書いててふと思ったのが、CSRF対策ってどういうサイトでするのって話を書くのを忘れていたなと。まとめに書くなよ感は否めませんが、基本的にログイン機能を持ち、更新処理があるようなサイトは対策が必須かなと思います。また、ログインしなくても投稿ができてしまうような掲示板も対策しとく方がいいと思います。
最後に私から言えることはコードレビューをしっかりしましょうですかね、今回はこれにて終わります。最後までありがとうございました。
参考
・『体系的に学ぶ 安全なWebアプリケーションの作り方 第2版』 著者:徳丸浩様