2026-07-28 · Team Fenrir
wp2shell: cómo comprobar si tu WordPress está expuesto
wp2shell es el nombre con el que se conoce una cadena de dos vulnerabilidades de WordPress — CVE-2026-63030 y CVE-2026-60137 — que juntas permiten la ejecución remota de código sin autenticación, en una instalación de WordPress por defecto y sin plugins. Las correcciones existen desde el 17 de julio de 2026. La explotación en la red está confirmada. Solo importa una pregunta operativa: ¿tu versión está entre las afectadas? Se comprueba con un comando.
¿Qué es wp2shell, en dos líneas?
No es un fallo: son dos, y solo cuentan cuando se ponen en fila.
- CVE-2026-63030 — un problema de route confusion en el endpoint REST de batch. NVD lo describe como un defecto que, «combinado con la inyección SQL de
author__not_inen WP_Query (CVE-2026-60137), podría permitir a un atacante realizar inyección SQL y lograr ejecución remota de código». - CVE-2026-60137 — WordPress «no sanea correctamente el parámetro
author__not_inde WP_Query», con posible inyección SQL «cuando un plugin o un tema pasa a ese parámetro entrada no confiable».
Leída bien, la segunda CVE por sí sola no es un desastre universal: hace falta que algo pase entrada no confiable a ese parámetro. Es la primera la que aporta precisamente eso, y sin credenciales. De ahí la gravedad: la cadena convierte dos defectos de alcance medio en un acceso previo a la autenticación. En términos de MITRE ATT&CK es un caso de manual de T1190 — Exploit Public-Facing Application: «los adversarios pueden intentar explotar una debilidad en un host expuesto a internet para obtener acceso inicial a una red».
Una nota de honestidad, ya que probablemente hayas llegado aquí buscando justo esa palabra: «wp2shell» no aparece ni en los registros CVE ni en el aviso de WordPress. Es la etiqueta que el sector le puso a la cadena. Los nombres oficiales son los dos CVE.
Sobre el funcionamiento interno nos detenemos aquí. El endpoint de batch no es un secreto — está documentado desde 2020, se introdujo en WordPress 5.6, acepta hasta 25 subpeticiones por llamada y se alcanza en /wp-json/batch/v1 — pero la mecánica del ataque no le sirve a quien tiene que defender, y la vulnerabilidad está bajo explotación activa. Lo que hace falta es saber si estás expuesto.
¿Soy vulnerable? La matriz de versiones
Esta es la tabla que importa. Está sacada de los registros de NVD y del anuncio oficial de publicación.
| Tu versión | CVE-2026-60137 (SQLi) | CVE-2026-63030 (cadena RCE) | Actualiza a |
|---|---|---|---|
| anterior a la 6.8 | no afectada | no afectada | sin soporte igualmente |
| de la 6.8.0 a la 6.8.5 | afectada | no afectada | 6.8.6 |
| de la 6.9.0 a la 6.9.4 | afectada | afectada | 6.9.5 |
| de la 7.0.0 a la 7.0.1 | afectada | afectada | 7.0.2 |
| 6.8.6 · 6.9.5 · 7.0.2 y posteriores | corregida | corregida | estás bien |
WordPress.org lo escribe sin rodeos: «WordPress 6.9 está afectada por ambas vulnerabilidades», «WordPress 6.8 solo está afectada por la primera», «las versiones de WordPress anteriores a la 6.8 no están afectadas». Ojo con esta última línea: no afectadas por estas dos CVE no significa seguras. Sigue valiendo el principio de que «solo la versión más reciente de WordPress recibe soporte activo».
Dos datos sobre la gravedad, con la atribución correcta, porque las fuentes no coinciden y conviene saberlo. En CVE-2026-63030 el CNA (WPScan) asigna CVSS 9,8, CRITICAL, mientras que el registro adicional de CISA-ADP asigna 7,5, HIGH. En CVE-2026-60137 la relación se invierte: 5,9 (MEDIUM) del CNA y 9,1 (CRITICAL) de CISA-ADP. No existe una puntuación primaria de NVD. Pero el número que decide la prioridad no es ninguno de estos: es que CISA incorporó ambas CVE al catálogo Known Exploited Vulnerabilities el 21 de julio de 2026, con fecha límite de remediación el 4 de agosto de 2026. En el catálogo KEV entra lo que consta como explotado en la red.
¿Cómo compruebo la versión desde la línea de comandos?
En el servidor. Con WP-CLI, una línea:
# La versión instalada
wp core version
# Con detalles adicionales (revisión de la BD, idioma del paquete)
wp core version --extra
Sin WP-CLI, la versión está en el escritorio bajo Actualizaciones, o en el número de abajo a la derecha del área de administración.
¿Y los «wp2shell checker» que interrogan el sitio desde fuera? Sirven para hacerse una idea a gran escala, no para certificar tu sitio. Una comprobación remota deduce la versión de readme.html o de la metaetiqueta generator: dos elementos que muchísimas instalaciones eliminan por costumbre de hardening, que las cachés pueden servir desactualizados y que un atacante ya dentro puede modificar. El resultado es que un escáner externo puede decirte «seguro» cuando no lo estás, o alarmarte en vano. La comprobación autorizada es la que se hace en el sistema de archivos. Si gestionas más de un sitio, esta es justo la diferencia entre saber y esperar: es la razón por la que Fenrir WP Bridge mantiene el inventario de versiones de todos los sitios en un único punto, en vez de dejarte abrir veinte escritorios.
¿Me han salvado ya las actualizaciones automáticas?
Quizá. No lo des por hecho, y no porque WordPress no haya hecho su parte: para esta versión el proyecto «activó actualizaciones forzadas mediante el sistema de auto-update en los sitios que ejecutaban versiones afectadas». Muchos sitios se actualizaron solos durante la noche del 17 de julio.
Quedan fuera cuatro categorías, y son más frecuentes de lo que parece:
- Sitios bajo control de versiones. Las actualizaciones automáticas del núcleo se desactivan cuando WordPress detecta un checkout de Git o SVN.
- Sitios con la constante
AUTOMATIC_UPDATER_DISABLEDdefinida enwp-config.php, o conWP_AUTO_UPDATE_COREenfalse. - Sitios en los que el cron de WordPress no se ejecuta — porque está desactivado, porque hay poco tráfico, porque se sustituyó por un cron de sistema mal configurado. La actualización automática necesita que algo la dispare.
- Sitios instalados antes de la 5.6 y nunca reconfigurados: hasta esa versión el valor por defecto solo cubría las versiones menores, y la configuración heredada permanece.
En los cuatro casos el sitio se quedó en la versión vulnerable mientras la explotación ya estaba en marcha. De ahí la regla: comprueba, no deduzcas.
¿Cómo sé si ya han entrado?
Si tu sitio estuvo expuesto con una versión vulnerable entre el 17 de julio y el momento de actualizar, actualizar no basta: cierra la puerta, no echa a quien ya está dentro. Cuatro comprobaciones, por orden de rendimiento.
1. Integridad de los archivos del núcleo. Compara cada archivo con las sumas de verificación oficiales de WordPress.org:
wp core verify-checksums --include-root
wp plugin verify-checksums --all
--include-root es la opción que cuenta: sin ella solo ves los archivos modificados; con ella, también te señala los archivos ajenos aparecidos en la raíz del sitio. Una puerta trasera rara vez modifica un archivo existente: normalmente añade uno. Si encuentras algo, lo que sigue es el oficio que se cuenta en cómo reconocer una web shell en WordPress: MITRE cataloga esa persistencia como T1505.003.
2. Administradores que no has creado. Es el indicador de compromiso más inmediato tras un RCE, y ATT&CK lo cataloga como T1136.001 (Create Account: Local Account). La columna que importa es la fecha de registro:
wp user list --role=administrator \
--fields=ID,user_login,user_email,user_registered
Un administrador registrado después del 17 de julio que no reconozcas es un incidente mientras no se demuestre lo contrario. La misma pregunta hay que hacérsela a los usuarios con rol de editor: un atacante cuidadoso no siempre va a por el privilegio máximo.
3. Tareas programadas ajenas. El cron de WordPress es un sitio cómodo para hacerse reejecutar:
wp cron event list --fields=hook,next_run,recurrence
Busca hooks cuyos nombres no pertenezcan ni al núcleo ni a tus plugins.
4. Registros del servidor web. Busca las peticiones POST hacia el endpoint de batch, en las dos formas en que puede aparecer según los enlaces permanentes:
grep -E 'POST .*(wp-json/batch/v1|rest_route=/batch/v1)' /var/log/nginx/access.log
Existe tráfico legítimo hacia ese endpoint — lo usa el editor de bloques — así que no es una alarma por sí mismo. Lo que cuenta es el contexto: ráfagas desde una única IP, agentes de usuario anónimos, peticiones desde redes que no tienen nada que ver con tus redactores y, sobre todo, una ráfaga seguida de apariciones sospechosas en las tres comprobaciones anteriores.
¿Qué hago si encuentro algo?
El procedimiento oficial de WordPress.org para un sitio comprometido es largo; estos son los puntos que más se equivocan.
- Documenta antes de limpiar. «El primer paso concreto que debes dar tras un compromiso es la documentación»: es la base del informe de incidente, y borrar con prisas destruye las pruebas necesarias para entender cómo entraron.
- No reinstales el núcleo desde el escritorio. La indicación oficial es explícita: «cuando reinstales, asegúrate de no usar las opciones de reinstalación de WP-ADMIN», porque esos instaladores «a menudo solo sobrescriben los archivos existentes, y los ataques suelen introducir archivos nuevos». Se reinstala la misma versión por SFTP, sustituyendo
/wp-adminy/wp-includes. - Rota las claves secretas, no solo las contraseñas. Cambiar las contraseñas no expulsa a quien ya tiene una sesión abierta. Hay que actualizar las secret keys de
wp-config.php: «esto obligará a salir a cualquiera que siga conectado». - Cambia las credenciales dos veces: una durante la limpieza y otra al terminarla, porque «tienes que cambiar las contraseñas del sitio después de asegurarte de que está limpio».
- Revisa
.htaccess, en todos los directorios donde aparezca: la documentación oficial lo señala como el archivo que más se modifica con fines maliciosos.
Si el sitio maneja datos de clientes o pedidos, a partir de aquí la pregunta deja de ser técnica y hay que llevarla a quien corresponda. Nosotros nos detenemos donde acaba el oficio: levantar el sitio y entender el vector.
Por qué la monitorización importa más que un parche suelto
wp2shell demuestra un problema estructural, no un caso aislado. La ventana entre la publicación de la corrección (17 de julio) y la entrada en el catálogo KEV (21 de julio) es de cuatro días: eso es lo que pasó entre «existe un parche» y «está confirmado que alguien lo está explotando en sitios reales». Dentro de esa ventana, la diferencia entre un sitio actualizado y uno parado no la marcó la pericia de nadie: la marcó un cron que se ejecutaba o no se ejecutaba.
Nadie lee el anuncio de seguridad de WordPress a las dos de la madrugada. Pero algo tiene que darse cuenta: de que ha salido una versión de seguridad, de que tres de tus veinte sitios no la han cogido, de que uno de esos tres tiene un administrador más que ayer. Es el trabajo de Fenrir para WordPress en los sitios y de Fenrir SOC en los servidores: inventario de versiones, integridad de archivos, correlación de registros y una respuesta que arranca antes de que abras el terminal. El parche lo aplicas una vez. Comprobar que sigue haciendo falta es un trabajo de cada noche.
Preguntas frecuentes
¿Qué versiones de WordPress son vulnerables a wp2shell?▾
La cadena completa (RCE sin autenticación) afecta a WordPress de la 6.9.0 a la 6.9.4 y de la 7.0.0 a la 7.0.1. La inyección SQL CVE-2026-60137 por sí sola afecta además a la rama 6.8, de la 6.8.0 a la 6.8.5. Las correcciones son 6.8.6, 6.9.5 y 7.0.2, publicadas todas el 17 de julio de 2026. Según WordPress.org, las versiones anteriores a la 6.8 no están afectadas.
¿Cómo sé qué versión de WordPress tengo?▾
En el servidor, no desde fuera. Con WP-CLI: `wp core version`. Desde el escritorio: Actualizaciones, o el número abajo a la derecha en el área de administración. Las comprobaciones remotas que leen readme.html o la metaetiqueta generator son solo indicativas: esas marcas suelen eliminarse o quedarse desactualizadas, así que pueden decirte «seguro» cuando no lo estás.
Si tengo las actualizaciones automáticas activadas, ¿ya estoy cubierto?▾
Probablemente sí, pero hay que comprobarlo. Para esta versión WordPress activó actualizaciones forzadas en los sitios con versiones afectadas. Quedan fuera los sitios bajo control de versiones, los que tienen AUTOMATIC_UPDATER_DISABLED o WP_AUTO_UPDATE_CORE definidos, y aquellos en los que el cron de WordPress no se ejecuta. Comprueba la versión: es un solo comando.
¿Cómo sé si mi sitio ya ha sido comprometido?▾
Tres comprobaciones, en este orden: `wp core verify-checksums --include-root` para archivos del núcleo modificados o ajenos; `wp user list --role=administrator` mirando la columna user_registered en busca de administradores aparecidos hace poco; `wp cron event list` para tareas programadas que no reconozcas. En los registros del servidor web, busca peticiones POST hacia /wp-json/batch/v1.
Actualicé después del 17 de julio, ¿estoy a salvo?▾
Estás a salvo de una explotación nueva, no de la que ya ocurrió. La actualización cierra la puerta, no expulsa lo que entró antes: cuentas de administrador creadas, archivos subidos, tareas programadas. Si el sitio estuvo expuesto con una versión vulnerable mientras la explotación estaba activa, haz las comprobaciones de compromiso después de actualizar.
Fuentes
- NVD — CVE-2026-63030 (route confusion en el endpoint REST batch)
- NVD — CVE-2026-60137 (inyección SQL en author__not_in de WP_Query)
- WordPress.org — WordPress 7.0.2 Security Release (17 de julio de 2026)
- WordPress — aviso oficial GHSA-ff9f-jf42-662q
- CISA — Known Exploited Vulnerabilities Catalog
- WP-CLI — wp core verify-checksums
- WordPress.org — FAQ: My site was hacked
- WordPress.org — Updating WordPress y actualizaciones automáticas
- Make WordPress Core — REST API batch framework (WordPress 5.6)
- MITRE ATT&CK — T1190 Exploit Public-Facing Application