カテゴリ: PHP 更新日: 2026/08/17

PHP の CSRF 対策(セッション・トークンを活用)

PHP の CSRF 対策(セッション・トークンを活用)
PHP の CSRF 対策(セッション・トークンを活用)

新人と先輩の会話形式で理解しよう

新人

「PHPでCSRF対策ってどうやるんですか?」

先輩

「CSRF攻撃を防ぐには、セッション・トークンを活用する方法があります。これで不正なリクエストを防ぐことができますよ。」

新人

「セッション・トークンって何ですか?」

先輩

「セッション・トークンは、フォームに埋め込むことで、ユーザーからの正当なリクエストかどうかを確認するためのものです。」

1. CSRFとは?

1. CSRFとは?
1. CSRFとは?

CSRF(Cross-Site Request Forgery)とは、ユーザーが意図しない操作を、ログイン中の状態を利用してウェブサイトに実行させる攻撃のことです。見た目は普通の操作に見えても、裏では別のリクエストが送られているのが厄介な点です。

ポイントは「ユーザー本人が送ったように見えるリクエスト」を作れてしまうことです。たとえば、会員情報の変更、パスワード変更、送金、退会など、ボタン1つで実行できる処理が狙われやすくなります。

具体的には、攻撃者が悪意を持って、ユーザーがログインしているウェブサイトに対して、第三者のページやメールなどを経由してリクエストを送信させます。例えば、ユーザーが銀行にログインしているときに、攻撃者がユーザーの名前で不正に送金させるようなことが起こります。

初心者向け:CSRFが起きるイメージ(例)

たとえば「メールアドレスを変更するフォーム」があり、ログインしていれば送信できるとします。攻撃者は別サイトに“こっそり送信されるフォーム”を置いて、ユーザーがそのページを開いただけで送信が走るようにすることがあります。


<!-- 攻撃者のページに置かれるイメージ(例) -->
<form action="https://example.com/change_email.php" method="POST">
    <input type="hidden" name="email" value="attacker@example.com">
    <input type="submit" value="クリック">
</form>

この例では、ユーザーがexample.comにログイン中だと「本人が変更した」ように見えるリクエストが送られてしまう可能性があります。だからこそ、サーバー側で「正当な画面から送られた操作か?」を確認する仕組みが必要になります。

2. CSRF攻撃がどのように行われるか

2. CSRF攻撃がどのように行われるか
2. CSRF攻撃がどのように行われるか

CSRF攻撃は、ユーザーが「何か操作しているつもりはない」のに、知らないうちにリクエストが送信されてしまう点が特徴です。特に、ログイン状態が維持されていることが悪用されます。

Webサイトは一度ログインすると、しばらくの間は自動的に認証された状態になります。そのため、ユーザー本人でなくても、条件がそろえば操作が成立してしまいます。

よくあるCSRF攻撃のパターン

  • 悪意のあるリンクをクリックさせる:メールやSNSに仕込まれたリンクをクリックしただけで、裏側でリクエストが送信されることがあります。
  • 別サイトに置かれたフォームを自動送信させる:ユーザーがページを開いた瞬間に、見えないフォームが送信されるケースもあります。

初心者向け:リンクを使った攻撃のイメージ

たとえば、次のようなURLがメールで送られてきたとします。一見すると普通のリンクですが、クリックすると処理が実行されてしまうことがあります。


<a href="https://example.com/delete_account.php">お知らせはこちら</a>

もしユーザーがexample.comにログイン中で、アクセスするだけで処理が実行される仕組みだった場合、「本人が退会操作をした」ように見えてしまいます。

このように、CSRF攻撃はユーザーの操作ミスではなく、仕組みの弱点を突いて行われます。そのため、サーバー側で「本当に正しい画面から送られたか」を確認する対策が必要になります。

3. CSRF対策のためのセッション・トークンとは?

3. CSRF対策のためのセッション・トークンとは?
3. CSRF対策のためのセッション・トークンとは?

CSRF攻撃を防ぐためによく使われるのが「セッション・トークン」という仕組みです。これは、その画面を表示した本人だけが持っている合言葉のようなものだと考えると分かりやすいでしょう。

セッション・トークンは、サーバー側でランダムに生成され、ユーザーごとのセッションに保存されます。そして、その値をフォームの中に隠して一緒に送信します。

サーバーは「送られてきたトークン」と「セッションに保存してあるトークン」を照合し、両方が一致した場合のみ処理を続行します。一致しなければ、正規の画面からの操作ではないと判断できます。

初心者向け:セッション・トークンの役割イメージ

イメージとしては、「この画面を開いた人だけに渡す整理券」をフォーム送信時に確認するようなものです。整理券がなければ、受付(サーバー)は処理を受け付けません。

PHPでセッション・トークンを作る基本例


<?php
// セッションを開始(トークンを使う前に必須)
session_start();

// ランダムな文字列を生成してトークンとして保存
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
?>

このコードでは、PHPのrandom_bytes()を使って予測されにくいランダムな値を作り、それをセッションに保存しています。bin2hex()は、扱いやすい文字列に変換するためのものです。

このトークンをフォームに埋め込み、送信時にチェックすることで、「別サイトから勝手に送られたリクエスト」を見分けられるようになります。CSRF対策の基本として、まずはこの仕組みをしっかり押さえておきましょう。

4. PHPでCSRF対策を実装する方法

4. PHPでCSRF対策を実装する方法
4. PHPでCSRF対策を実装する方法

ここからは、実際にPHPでCSRF対策を動かすための具体的な手順を見ていきます。流れとしては「トークンを作る → フォームに埋め込む → 送信時に確認する」という3ステップです。

難しく感じるかもしれませんが、1つずつ見ていけばシンプルなので、仕組みをイメージしながら読み進めてみてください。

4.1 フォームにセッション・トークンを埋め込む

まずは、フォームを表示する画面でセッション・トークンを埋め込みます。大事なのは、session_start()を忘れずに書くことです。

このトークンは画面を表示した時点で発行され、その画面から送信されたかどうかを判断する材料になります。


<?php
session_start();

// トークンがなければ作成
if (!isset($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>

<form method="POST" action="submit.php">
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
    <button type="submit">送信</button>
</form>

ここでは、フォームの中にtype="hidden"の入力欄を使ってトークンを仕込んでいます。画面には表示されませんが、送信時に一緒に送られます。

4.2 送信されたトークンを検証する

次に、フォームが送信された後の処理です。サーバー側では「送られてきたトークン」と「セッションに保存してあるトークン」が一致するかを必ず確認します。

このチェックがあることで、別サイトから勝手に送られたリクエストを弾くことができます。


<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (
        isset($_POST['csrf_token']) &&
        isset($_SESSION['csrf_token']) &&
        $_POST['csrf_token'] === $_SESSION['csrf_token']
    ) {
        echo '正当なリクエストです。処理を続行します。';
        // ここに本来の処理を書く
    } else {
        echo '不正なリクエストの可能性があります。';
        // 処理を中断する
    }
}
?>

このように、トークンが一致した場合だけ処理を進めるのがポイントです。もし一致しなければ、その時点で処理を止めます。

この仕組みを入れておくだけで、CSRF攻撃の多くを防げるようになります。フォーム送信を扱うページでは、必ずセットで実装するようにしましょう。

5. CSRF対策のセッション・トークンを使うメリットとデメリット

5. CSRF対策のセッション・トークンを使うメリットとデメリット
5. CSRF対策のセッション・トークンを使うメリットとデメリット

CSRF対策としてセッション・トークンを使う方法は、多くのWebアプリケーションで採用されています。ただし、便利な反面、理解しておきたい注意点もあります。

メリット

  • セキュリティ向上:正規の画面で発行されたトークンがない限り処理を受け付けないため、第三者による不正なリクエストを防げます。
  • 仕組みが分かりやすい:「発行したトークンと一致するかを確認する」という単純な仕組みなので、初心者でも理解しやすいのが特徴です。
  • ユーザーを守れる:ログイン状態が悪用されても、トークンが一致しなければ処理されないため、意図しない操作を防止できます。

デメリット

  • セッション管理が必要:セッションを使うため、session_start()の書き忘れや管理ミスがあると正しく動かなくなります。
  • 実装箇所が増える:フォームごとにトークンの埋め込みとチェックが必要になり、画面数が多いと実装量が増えます。

それでも、セッション・トークンによるCSRF対策は「基本かつ必須」と言える方法です。まずはこの仕組みを正しく実装できるようになることが、安全なPHPアプリケーション作成への第一歩になります。

6. 実際のプロジェクトでの活用方法(フォーム送信など)

6. 実際のプロジェクトでの活用方法(フォーム送信など)
6. 実際のプロジェクトでの活用方法(フォーム送信など)

ここでは、実務でよく登場する場面を想定しながら、CSRF対策をどのように組み込むかを確認します。ポイントは「特別な画面だけでなく、送信処理がある場所すべてに対策を入れる」ことです。

6.1 フォーム送信時のCSRF対策

お問い合わせフォームや登録フォームなど、ユーザーが入力して送信する画面では、必ずセッション・トークンを埋め込みます。これにより、その画面を開いた本人の操作かどうかを判別できます。

プログラミング未経験の方は、「送信ボタンを押したときの身分証明書を一緒に送る」と考えると理解しやすいでしょう。


<?php
session_start();
echo '<form method="POST" action="submit.php">';
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';
echo '<input type="submit" value="送信">';
echo '</form>';
?>

このように、フォームごとにトークンを仕込むだけで、外部サイトからの不正な送信を防げます。

6.2 トークンの検証

次に、送信先の処理です。ここでは必ず「送られてきたトークン」と「セッション内のトークン」を比較します。この確認を省略すると、CSRF対策の意味がなくなってしまいます。


<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['csrf_token']) && $_POST['csrf_token'] === $_SESSION['csrf_token']) {
        echo 'リクエストが正当です。';
        // データ保存などの処理
    } else {
        echo '不正なリクエストです。';
        // 処理を中止
    }
}
?>

一致しなければ、その時点で処理を止めることが重要です。これがCSRF対策の「最後の砦」になります。

6.3 ログイン機能への適用

ログイン画面も例外ではありません。ログイン処理はユーザーの権限に直結するため、CSRF対策を入れておくと安心です。


<?php
echo '<form method="POST" action="login.php">';
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';
echo 'ユーザー名: <input type="text" name="username"><br>';
echo 'パスワード: <input type="password" name="password"><br>';
echo '<input type="submit" value="ログイン">';
echo '</form>';
?>

このように、フォーム送信がある機能にはまとめてCSRF対策を入れておくことで、実際のプロジェクトでも安全性を保ちやすくなります。

7. 今後の学習方法

7. 今後の学習方法
7. 今後の学習方法

ここまでで、PHPにおけるCSRF対策の基本として「セッション・トークンを使う方法」を理解できたと思います。フォーム送信の仕組みとあわせて考えることで、なぜこの対策が必要なのかもイメージしやすくなったはずです。

今後の学習では、まずセッションの仕組みそのものをもう一度整理してみましょう。セッションIDの役割や、ログイン状態がどのように維持されているかを理解すると、CSRF対策の意味がよりはっきりします。

次のステップとしては、トークンを「いつ作り、いつ無効にするのか」といった運用面を考えることも大切です。画面を更新したら新しいトークンを発行する、処理が終わったら使えなくするなど、実際の動きを想像しながら学ぶと理解が深まります。

また、CSRF以外にも、入力値チェックや認証まわりなど、Webアプリケーションにはさまざまなセキュリティ対策があります。今回学んだ内容を土台にしながら、1つずつ知識を積み重ねていくことで、安全なPHPアプリケーションを作れるようになるでしょう。

まとめ

まとめ
まとめ

PHPでウェブアプリケーションを開発する上で、CSRF(クロスサイト・リクエスト・フォージェリ)攻撃の対策は欠かせない要素の一つです。この記事では、CSRF攻撃がどのように行われるのか、その脅威を理解した上で、セッション・トークンを用いた安全なリクエストの仕組みを学びました。

CSRF攻撃は、ユーザーが意図しない形で悪意ある操作を実行させられるリスクのある攻撃です。ユーザーがログイン中の状態で、不正なフォームやリンクを踏まされることで、意図しない送金や設定変更などが実行されてしまいます。こうした事態を防ぐには、サーバー側でリクエストの正当性を確認する仕組みが重要となります。

そのために活用されるのが、セッション・トークンです。このトークンは、bin2hex(random_bytes(32))などを使ってランダムに生成され、セッション変数$_SESSION['csrf_token']に保存されます。そして、フォームにはこのトークンを埋め込んで送信し、受信時にサーバーが照合することで、リクエストが本物かどうかを判断します。

たとえば次のように実装します:


<?php
session_start();

// トークン生成
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// フォーム出力
echo '<form method="POST" action="submit.php">';
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';
echo '<input type="submit" value="送信">';
echo '</form>';
?>
    

フォーム送信後には次のようにしてトークンを検証します:


<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!empty($_POST['csrf_token']) && hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
        echo 'リクエストが正当です。';
    } else {
        echo 'CSRF攻撃の可能性があります。';
    }
}
?>
    

hash_equals()を使うことで、タイミング攻撃を防ぎつつ、トークンの一致を安全に検証できます。セッション・トークンの管理は一見手間がかかるようにも思えますが、その手間に見合うセキュリティ効果があります。特にログインフォームやユーザー情報の更新など、重要な操作を伴う機能には積極的に取り入れるべきです。

今後の開発では、セッション・トークンの再生成や有効期限の設定など、より高度な対策も検討しながら、安全なWebアプリケーションの構築を心がけましょう。

先生と生徒の振り返り会話

生徒

「CSRF攻撃って、ただのリンクをクリックするだけでも起きるって聞いて怖くなりました……。」

先生

「そうだね。知らないうちに他人の操作として処理されることがあるから、セキュリティ対策は大事なんだ。」

生徒

「セッション・トークンを使えば、正しいフォームからの送信かどうかをチェックできるんですね。」

先生

「そのとおり。セッションに保存したトークンと送信されたトークンが一致すれば、正当なリクエストとして受け取れる仕組みだよ。」

生徒

「フォームに毎回隠しフィールドを入れるのはちょっと面倒に思えましたけど、それでセキュリティが守れるなら頑張って実装します!」

先生

「よく頑張ってるね。慣れてくるとテンプレート化して楽になるし、セッション・トークンは安全なウェブ開発の基本になるから、しっかり身につけておこう。」

生徒

「はい!今度はトークンの有効期限の管理や再生成についても勉強してみたいです!」

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

PHPでCSRF攻撃とは具体的にどのような被害が発生しますか?

PHPでのCSRF攻撃では、ユーザーが意図しない送金処理や設定変更が実行されてしまう恐れがあり、セッションを悪用されることで重大なセキュリティ事故につながります。

CSRF対策としてPHPでセッション・トークンを使う理由は何ですか?

セッション・トークンを使うことで、正当なリクエストかどうかを確認でき、CSRF攻撃による不正なフォーム送信やリンク操作を防ぐ効果があります。

PHPでCSRFトークンはどこで生成するのが適切ですか?

CSRFトークンはフォームを表示する前に、セッション開始後に生成し、セッション変数に保存しておくことが一般的です。
コメント
コメント投稿は、ログインしてください

まだ口コミはありません。

PHP のセッション管理の記事一覧へ
新着記事
New1
Gemini
GeminiでPHPコードを学ぶ方法!初心者向けに始め方と学習手順を解説
New2
PHP
PHP のセッション変数を保存・取得・削除する方法
New3
PHP
PHP のコンストラクタ(__construct)とは?使い方を解説
New4
Claude
ClaudeでPythonデバッグを解決する方法!Pythonデバッグのエラーメッセージを長いログから読み解く方法
人気記事
No.1
Java&Spring記事人気No1
Python
Pythonでディレクトリを作成・削除・一覧表示する方法!初心者向けにosとpathlibを使った使い方を解説
No.2
Java&Spring記事人気No2
Gemini
GeminiでPython自動化を始める時の質問文!目的と前提を伝えるコツ
No.3
Java&Spring記事人気No3
Claude
ClaudeにPHPコードをレビューしてもらう方法!安全性と保守性を同時に確認するチェックリスト
No.4
Java&Spring記事人気No4
PHP
PHP のフォームデータの受け取り($_POST, $_GET)を完全解説!初心者向けガイド
No.5
Java&Spring記事人気No5
Gemini
GeminiにPHPエラーを相談する時のコードの貼り方!原因特定を早めるコツ
No.6
Java&Spring記事人気No6
Claude
Claudeを使ったPythonコードレビューの進め方!設計意図と処理の流れを表で確認する質問例
No.7
Java&Spring記事人気No7
PHP
PHP のインストール方法(Windows・Mac・Linux)と開発環境
No.8
Java&Spring記事人気No8
Python
Pythonで文字列が数値か判定する方法!isdigit()・isnumeric()の違い