前の記事では、
XSS(クロスサイトスクリプティング) について学びました。
XSSは
「表示時の安全性」がテーマでしたが、
今回扱う CSRF は
「意図しない操作をさせられる危険性」 がテーマです。
フォーム処理を行うPHPでは、
CSRF対策は必須 です。
この記事では、
CSRFとは何か、どのように攻撃されるのか、
PHPでの基本的な対策方法 を
コード付きで解説します。
この記事で学べること
・CSRFとは何か
・CSRF攻撃の仕組み
・なぜCSRFが危険なのか
・PHPでの基本的なCSRF対策
・XSSとの違い
CSRFとは何か
CSRF(Cross Site Request Forgery)とは、
ユーザーが意図しないリクエストを、
正規ユーザーとして送信させられてしまう攻撃 です。
日本語では、
クロスサイト・リクエスト・フォージェリ
と呼ばれます。
CSRFのポイントは「なりすまし」
CSRFの最大の特徴は、
・攻撃者がログインするわけではない
・被害者がログインした状態を利用する
という点です。
つまり、
「ログイン中のユーザー自身が、
気づかないうちに操作してしまう」
これがCSRFです。
CSRF攻撃の典型的な流れ
CSRF攻撃は、
次のような流れで行われます。
-
ユーザーがWebサービスにログイン
-
ログイン状態のまま、別の悪意あるサイトを閲覧
-
そのサイトから、勝手にリクエストが送信される
-
サーバーは「正規ユーザーの操作」と判断
-
処理が実行されてしまう
CSRFが起きると何が問題か
CSRFが起きると、
次のような被害が発生します。
・パスワード変更
・メールアドレス変更
・退会処理
・投稿・削除操作
これらが
本人の意思とは無関係に実行
される可能性があります。
なぜCSRFが起きるのか
CSRFが起きる原因は、
次の一点に集約されます。
「そのリクエストが本当に本人の操作かどうかを確認していない」
サーバー側が、
・ログインしている
という理由だけで
・正当な操作だと判断
してしまうことが問題です。
XSSとCSRFの違い
混同しやすいので、
ここで整理します。
・XSS
→ 不正なスクリプトを実行させる
・CSRF
→ 不正なリクエストを実行させる
どちらも危険ですが、
攻撃の方向性が違う
点を理解しておきましょう。
CSRF対策の基本は「トークン」
CSRF対策の基本は、
CSRFトークン を使う方法です。
トークンとは、
・推測できない文字列
・フォームごとに発行
・送信時に一緒に送る
という仕組みです。
CSRFトークンの考え方
CSRFトークンを使うと、
・正規のフォームから送信されたか
・第三者サイトからの送信ではないか
を判定できます。
「正しいトークンがあるかどうか」
が、判断材料になります。
PHPでCSRFトークンを生成する
まずは、
トークンを生成して
セッションに保存します。
サンプルコード①:トークン生成
コードの解説
・session_start
→ セッションを使う
・random_bytes
→ 安全なランダム文字列生成
・$_SESSION に保存
このトークンは、
ユーザーごとに保持 されます。
フォームにトークンを埋め込む
次に、
フォームにトークンを含めます。
サンプルコード②:フォーム側
ポイント
・hidden フィールドで送信
・ユーザーには見えない
・正規フォームからしか送れない
これがCSRF対策の要です。
送信時にトークンを検証する
フォーム送信後、
PHP側でトークンを確認します。
サンプルコード③:トークン検証
コードの解説
・トークンが存在するか
・セッションの値と一致するか
どちらかでも失敗したら、
処理を中断 します。
CSRF対策は「更新系処理」に必須
CSRF対策は、
特に次の処理で必須です。
・登録
・更新
・削除
・設定変更
逆に、
・表示のみ
・検索
などでは、
必須ではないケースもあります。
初心者がよくやるミス
CSRF対策で多いミスです。
・ログインしているから安心と思う
・トークンを検証していない
・GETリクエストで更新処理を行う
「更新処理=CSRF対策必須」
と覚えてください。
フレームワークがCSRF対策をする理由
Laravelなどのフレームワークが
CSRF対策を自動で行うのは、
・人為的ミスが起きやすい
・忘れると致命的
だからです。
基礎を理解しておくことで、
フレームワークの仕組みも
正しく理解できます。
まとめ
CSRFは、
・ログイン中のユーザーを利用した
・意図しない操作を行わせる攻撃
です。
対策の基本は、
・CSRFトークンを発行
・フォームに埋め込む
・送信時に検証する
この流れを守ることです。
ここまで理解できれば、
PHPフォーム処理は「実務レベルの安全性」
に到達しています。
次に読むべき記事
▶ 次の記事
6-12 PHPでセッションを使って状態を管理する
▶ 関連記事
6-10 XSSとは?なぜ危険なのか



コメント