この記事の目的:WordPressのnonceとCSRFの関係を整理し、「nonceを入れれば安全」という誤解を避けながら、フォーム・管理操作・Ajax処理で必要な防御を実装できるようにします。
CSRFとは何か
CSRF(Cross-Site Request Forgery)は、WordPressへログイン中の利用者に、本人が意図していない状態変更リクエストを送らせる攻撃です。攻撃者が管理者のパスワードを知っている必要はなく、ブラウザーが保持しているログイン状態を悪用して、設定変更や削除などを実行させようとします。
そのため「ログイン済みだから正規操作」「POSTだから安全」とは判断できません。状態を変更する処理では、その操作が正規画面から意図して送られたものかを確認する仕組みが必要です。
WordPress nonceが担当する範囲
WordPressのnonceは、一般的な暗号学上の一回限りのnonceとは異なり、一定時間有効な検証値です。フォームでは wp_nonce_field()、独自処理では wp_verify_nonce()、管理画面では check_admin_referer()、Ajaxでは check_ajax_referer() などを利用できます。
nonceが正しいことだけを理由に管理操作を許可してはいけません。WordPress公式資料も、nonceをauthentication / authorization / access controlの代替として使用しないよう説明しています。
nonce・認証・権限を分離する
安全な状態変更処理は、少なくとも「利用者が誰か」「その利用者に操作権限があるか」「リクエストが正規の操作フローから来たか」を分けて確認します。WordPressではログイン状態だけでなく、current_user_can() 等によるCapability確認を行い、その上でnonceを検証します。
入力検証・サニタイズ・エスケープは別の防御
nonceが正しくても、受け取った値が安全とは限りません。ID、URL、メールアドレス、選択値などは想定する型・範囲・候補に合っているかを検証し、保存用途に応じて適切にsanitizeします。画面へ出力するときは、HTML、属性、URLなど出力先の文脈に合わせてescapeします。
CSRF対策とXSS・不正入力対策を一つの機能として扱わず、それぞれ別の責務として実装することが重要です。
管理画面の処理
管理画面で設定保存や削除を行う場合、フォームにnonceを生成し、受信側で検証します。さらにCapabilityを確認し、対象IDなどの入力値を検証してから更新します。nonce検証に失敗した後も処理を続ける実装は避け、状態変更前に検証を完了させます。
wp_nonce_field( 'sneng_save_settings', 'sneng_nonce' );check_admin_referer( 'sneng_save_settings', 'sneng_nonce' );current_user_can( 'manage_options' );Ajax処理で確認すること
Ajaxでも考え方は同じです。JavaScriptから送るnonceをサーバー側で check_ajax_referer() 等により検証し、ログイン利用者の権限が必要な操作ではCapabilityも別に確認します。nonce検証だけで任意の投稿IDやユーザーIDを操作できる構造にしないことが重要です。
REST APIでは認証方式と用途を確認する
REST APIでは、利用する認証方式やエンドポイントの性質によって防御方法が異なります。WordPressのCookie認証を利用するRESTリクエストではnonceが関係しますが、Application Passwordsなど別の認証方式まで一律に「nonce必須」と考えるのは正確ではありません。どの認証コンテキストで処理されるかを先に確認します。
nonceの期限切れを障害と攻撃で混同しない
長時間開いた管理画面やフォームでは、nonceの有効期間との関係で検証に失敗する場合があります。検証失敗を即座に攻撃と断定せず、画面を再読み込みして新しいnonceを取得した場合に正常化するか、キャッシュが古いHTMLを配信していないかなどを確認します。ただし、失敗時に検証を迂回する修正を行ってはいけません。
キャッシュとの相性
nonceを含む画面をフルページキャッシュすると、古いnonceが長時間配信される場合があります。公開フォームや会員画面をキャッシュする構成では、nonce生成部分をどのように扱うかを確認します。障害対策としてnonce検証そのものを削除するのではなく、キャッシュ設計を修正します。
現場での確認ポイント
- 状態を変更する処理にnonce生成と検証の両方があるか
- nonceとは別にCapability確認を行っているか
- 入力値を型・範囲・許可値でvalidationしているか
- 保存時のsanitizeと出力時のescapeを用途別に行っているか
- 検証失敗後に更新・削除処理が実行されないか
- Ajax・REST・通常フォームを同じ前提で扱っていないか
- キャッシュにより期限切れnonceが配信されていないか
よくある危険な実装
「nonceが一致したので管理者操作を許可する」「POSTならCSRF対策済みと考える」「権限確認なしでIDを受け取り削除する」「nonceエラーが出るため検証コードを外す」といった実装は避けます。nonceは重要な防御ですが、セキュリティ全体の一要素です。
一次資料
- WordPress Developer Resources:Nonces
- WordPress Developer Resources:Checking User Capabilities
- WordPress Developer Resources:Sanitizing Data
- WordPress Developer Resources:Escaping Data
関連技術と一緒に読む
サイト侵害時の初動や不審アクセスの記事は「攻撃を受けた後・受けている可能性がある状況」を扱います。本記事はその前段となる、WordPress機能を実装するときのCSRF防御と権限制御を扱います。役割を分けて読むことで、予防設計とインシデント対応を混同せず整理できます。