WordPressで考えるCSRF|メール変更機能を悪用する攻撃【WSAラボ解説】

Web Security Academy「CSRF vulnerability with no defenses」ラボでは、CSRFの最も基本的な攻撃パターンを体験できます。

このラボでは、メールアドレス変更機能にCSRF対策が実装されておらず、攻撃者が用意したHTMLを踏ませるだけで、ユーザーのメールアドレスを書き換えることができます。

この記事では、このラボの流れをもとに、CSRFの仕組みとWordPressにおけるリスクを解説します。

CSRF vulnerability with no defensesラボの概要

対象の機能は以下です。

  • ログインユーザーのメールアドレス変更機能
  • CSRFトークンなし
  • Cookieのみで認証

この状態では、外部サイトからリクエストを送るだけで、ユーザーの情報を変更できます。

CSRF攻撃が成立する3つの条件

CSRFが成立する条件はシンプルです。

  • ログイン状態であること(Cookie認証)
  • リクエストに予測不能な値がない
  • サーバーがリクエストの正当性を検証していない

このラボは、これらすべてを満たしています。

メールアドレス変更リクエストの中身

メール変更時のリクエストは以下のようになっています。

POST /my-account/change-email HTTP/1.1
Host: lab-id.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Cookie: session=xxxxemail=test@example.com

ポイントは以下です。

  • emailパラメータのみで処理される
  • CSRFトークンが存在しない
  • Cookieでユーザー識別している

CSRF PoCの作り方

このリクエストは、そのままHTMLに変換できます。

<html>
<body>
<form action="https://lab-id.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="attacker@evil.com">
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>

このHTMLがCSRF PoCです。


CSRF攻撃の流れ

ユーザーがこのページを開くと、以下が発生します。

  1. フォームが自動送信される
  2. ブラウザがセッションCookieを自動付与
  3. サーバーは本人の操作と誤認
  4. メールアドレスが変更される

この間、ユーザーは何も操作していません。


Exploit Serverの役割|被害者のブラウザからリクエストを送る仕組み

このラボでは、CSRF攻撃の検証にExploit Serverを使用します。

一見すると、Burp Repeaterから同じリクエストを送れば再現できそうに見えますが、CSRFはそれでは成立しません。

Repeaterではなぜ成立しないのか

Repeaterから送るリクエストは自分の操作です。

そのため、自分のCookieが使われ、CSRFにはなりません。

CSRFで重要なのは被害者のブラウザ

CSRFは、被害者のブラウザからリクエストが送られて初めて成立します。

ブラウザはリクエスト時に自動でCookieを付与するため、サーバーは本人の操作と判断してしまいます。

Exploit Serverの役割

Exploit Serverは、攻撃用ページを配置するための環境です。

被害者がアクセスすると、次の流れが発生します。

  • フォームが自動送信される
  • 被害者のブラウザがリクエストを送る
  • Cookieが自動で付与される
  • サーバーが本人と誤認する

このセクションの要点

CSRFは、被害者のブラウザを利用してリクエストを送らせる攻撃です。

  • Burp Repeater:リクエストの確認
  • Exploit Server:攻撃の実行

この違いを理解することが重要です。


WordPressで同じ問題が起きるケース

WordPressでも同様の構造は存在します。

  • /wp-admin/profile.php(プロフィール更新)
  • /wp-admin/options.php(設定変更)
  • プラグインの設定フォーム

これらの処理が以下の状態だと危険です。

  • nonce(CSRFトークン)がない
  • Cookieだけで認証している
  • パラメータが単純

攻撃者視点で考えると

このラボのような環境では、攻撃者は以下を行うだけです。

  • メール変更リクエストを取得
  • HTMLに変換
  • 被害者に踏ませる

特別な技術は不要で、リクエストの再現ができれば成立します。


XSSとCSRFの関係|組み合わせると何が起きるのか

CSRFは単体でも成立しますが、XSSと組み合わさるとさらに危険です。

XSSがある場合、攻撃者はサイト内部でスクリプトを実行できます。

fetch("/my-account/change-email", {
method: "POST",
credentials: "include",
body: "email=attacker@evil.com"
});

この場合、ユーザーがページを見るだけで攻撃が実行されます。


CSRF対策|WordPressにおけるnonceの重要性

WordPressでは、CSRF対策として「nonce(ナンス)」が使用されています。

nonceは、リクエストごとに付与される一時的なトークンで、サーバー側で検証されます。

nonceがない場合

nonceが存在しない場合、攻撃者はリクエストをそのまま再現できます。

今回のラボのように、パラメータが単純な場合は特に危険です。

nonceがある場合

nonceが含まれると、リクエストは以下のようになります。

POST /wp-admin/profile.php
...
email=user@example.com&_wpnonce=abc123

この値は予測できないため、攻撃者は正しいリクエストを再現できません。

WordPressでの実装例

WordPressでは、フォームに以下のようにnonceを埋め込みます。

wp_nonce_field('update-profile');

サーバー側では、wp_verify_nonce() によって検証されます。

重要なポイント

nonceはユーザー本人かどうかではなく、正規の画面から送られたかを確認する仕組みです。

nonceを適切に使用することで、CSRF攻撃を防げます。


WordPressセキュリティ診断でのチェックポイント

CSRFは設定ミスや実装漏れで簡単に発生する脆弱性です。

WordPressサイトを診断する際は、以下のポイントを確認します。

フォームにnonceが含まれているか

WordPressでは、CSRF対策としてnonceが使用されます。

確認ポイント

  • フォームに _wpnonce が含まれているか
  • wp_nonce_field() が使われているか

nonceがない場合、リクエストの再現が可能になります。

nonceの検証が実装されているか

フォームにnonceがあっても、サーバー側で検証していなければ意味がありません。

確認ポイント

  • wp_verify_nonce() が使われているか
  • 検証失敗時に処理が中断されるか

重要な操作がPOSTで送信されているか

設定変更などの重要な処理がGETで実装されている場合、CSRFのリスクが高まります。

確認ポイント

  • 状態変更系処理がPOSTになっているか
  • URLパラメータだけで処理されていないか

外部からリクエストを再現できないか

Burp Suiteなどを使い、リクエストの再現性を確認します。

確認ポイント

  • トークンなしでリクエストが通るか
  • パラメータが単純すぎないか

プラグインの実装を確認する

CSRFはテーマやプラグインの実装ミスで発生することが多いです。

確認ポイント

  • 独自フォームにnonceがあるか
  • AJAX処理でnonce検証が行われているか

CSRFは「リクエストが再現できるかどうか」を基準に判断するのがポイントです。


まとめ|CSRFはブラウザの自動送信を悪用する攻撃

このラボのポイントは以下です。

  • Cookieだけの認証は危険
  • リクエストが再現できると攻撃可能
  • 被害者のブラウザが勝手にリクエストを送る

CSRFは難しい攻撃ではなく、設計ミスで簡単に成立します。

WordPressでもnonceを適切に使わないと、同じ問題が発生します。