WordPressのnonceを理解しセキュアな機能開発へステップアップ – [CVE-2025-1463]脆弱性解説

by

in

WordPressの開発において、セキュリティ対策は不可欠です。

特にCSRF(クロスサイトリクエストフォージェリ)攻撃への対策として、WordPressではnonce(ナンス)と呼ばれるトークンを使用します。

本記事では、CVE-2025-1463(Spreadsheet IntegrationプラグインのCSRF脆弱性)を例に、WordPressテーマやプラグインの開発者が安全な機能開発にステップアップできるように、nonceの使い方を詳しく解説します。


CVE-2025-1463とは?

CVE-2025-1463は、WordPressのSpreadsheet Integrationプラグインに発生したCSRFの脆弱性です。

https://nvd.nist.gov/vuln/detail/CVE-2025-1463

問題の原因

  • WordPressにはnonceを使ったCSRF対策の仕組みがあるが、このプラグインではnonceチェックが適切に実装されていなかった
  • その結果、攻撃者が管理者に悪意のあるリクエストを送信させることが可能になった。
  • 具体的には、管理者が特定のリンクをクリックするだけで、意図しない投稿の公開や設定変更が行われる可能性があった。

このような問題を防ぐために、nonceの正しい実装が重要になります。

(ちなみに、該当の脆弱性は既に解決済みでプラグインのアップデートをすることで堅牢な処理になります。)

修正コードはこちらで確認できます: https://plugins.trac.wordpress.org/changeset/3250077/#file352

CSRFによる問題点

CSRF(クロスサイトリクエストフォージェリ)は、攻撃者がユーザーのブラウザを悪用し、意図しないリクエストを送信させる攻撃です。

CSRFの危険性

  • 管理者権限の乗っ取り
    管理者がログイン中の状態で悪意のあるリンクを踏むと、意図しない投稿の公開・削除、設定の変更が行われる可能性があります。
  • データ改ざん
    ユーザーのアカウント情報を変更するリクエストを送信されると、被害者は知らない間にパスワードを変更されることがあります。
  • 不正送金やアカウントの悪用
    ECサイトや銀行系のシステムでは、CSRFにより不正な取引が発生することもあります。

CSRFの具体的な攻撃手法

攻撃者が悪意のあるWebページを作成

攻撃者は、対象サイトの特定の機能(投稿の削除、設定変更など)を実行するための悪意のあるリクエストを含んだページを作成します。

権限を持つユーザーを誘導

攻撃者は、ターゲットユーザー(例:WordPressの管理者)をそのページに誘導するため、

  • フィッシングメール
  • SNSのメッセージ
  • 広告

などを使用してクリックさせます。

ユーザーがリンクをクリックすると不正リクエストが送信される

被害者がログイン中の状態でそのページを開くと、意図しないリクエストが発生し、サイトの設定が変更される可能性があります。

本件のCSRFは過去のmixiで起きた事例が参考になります。

これを防ぐために、nonceの正しい実装が必要になります。

WordPressのnonceとは?

nonce(ナンス)は、一時的に有効なユニークなトークンで、CSRF攻撃を防ぐために使用されます。WordPressの標準機能として提供されており、以下の特徴があります。

  • セッションごとに一意のトークンを発行
  • 特定のアクション(delete_postなど)に対して有効
  • 一定時間(デフォルト12時間)で無効になる

この仕組みにより、悪意のあるサイトからの不正なリクエストをブロックできます。

WordPressでのnonceの使い方

nonceの生成(フォームやリンクに埋め込む)

フォームのnonce埋め込み

<form method="post" action="admin-post.php">
    <?php wp_nonce_field('delete_post', 'my_nonce'); ?>
    <input type="hidden" name="post_id" value="123">
    <input type="submit" value="削除">
</form>

wp_nonce_field($action, $name) を使用すると、隠しフィールドにnonceが埋め込まれるため、安全なリクエストが可能になります。

  • $action(delete_post) → このnonceが有効なアクション名
  • $name(my_nonce) → フォーム内のname属性

リンクにnonceを付与(GETリクエスト用)

$url = add_query_arg('_wpnonce', wp_create_nonce('delete_post'), 'admin.php?page=delete&id=123');
echo '<a href="' . esc_url($url) . '">削除</a>';

wp_create_nonce('delete_post') で生成されたnonceをGETパラメータとして付与します。

nonceの検証(リクエストをチェック)

POSTリクエストのnonce検証

if ( ! isset($_POST['my_nonce']) || ! wp_verify_nonce($_POST['my_nonce'], 'delete_post') ) {
    wp_die('Security check failed');
}
  • isset($_POST['my_nonce']) → nonceが送信されているか確認
  • wp_verify_nonce($_POST['my_nonce'], 'delete_post') → nonceが正しいか検証

管理画面用のnonceチェック(フォーム送信時)

if (isset($_POST['submit'])) {
    check_admin_referer('delete_post', 'my_nonce');
    // 正常な処理を実行
}

check_admin_referer() は、nonceのチェックを簡単に実装できるWordPress標準関数です。

Ajaxリクエストのnonceチェック

フロントエンドでnonceを送信

jQuery.post(
    ajaxurl,
    {
        action: 'delete_post',
        security: my_ajax_object.nonce,
        post_id: 123
    },
    function(response) {
        console.log(response);
    }
);

サーバー側(functions.php)のnonceチェック

add_action( 'wp_ajax_delete_post', 'delete_post_function' );

function delete_post_function() {
    check_ajax_referer('delete_post', 'security');
    
    $post_id = intval($_POST['post_id']);
    wp_delete_post($post_id);
    
    wp_send_json_success('削除しました');
}
  • check_ajax_referer('delete_post', 'security'); でnonceを検証
  • CSRF攻撃を防ぐための標準的な方法

まとめ

関数説明
wp_create_nonce($action)nonceを生成
wp_verify_nonce($nonce, $action)nonceを検証
wp_nonce_field($action, $name)フォームにnonceを埋め込む
check_admin_referer($action, $name)管理画面用のnonceチェック
check_ajax_referer($action, $name)Ajaxリクエストのnonceチェック

開発者として次のステップへ

WordPressで機能を開発する際には、CSRF対策としてnonceを正しく実装することが必須です。

特に、

  • 管理画面の操作
  • 投稿の削除・編集機能
  • Ajaxリクエスト

を開発する際は、適切にnonceを使用して安全なコードを書く習慣を身につけましょう。

今後のステップとして、

  • REST APIでのnonceの扱い
  • wp_rest_nonceを利用したAPI認証

など、さらに高度なセキュリティ対策も学んでいくことをおすすめします。

参照リンク

レンタルサーバーを最大限使いこなすための方法

Laravelの記事を厳選して紹介

投稿者


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA