
Escanea WordPress Core 4.7.0–7.1.1 en busca de CVE-2026-87902, un LFI no autenticado mediante el recorrido de rutas con doble codificación en el parámetro pagename, con escalada opcional a RCE mediante PEAR config-create y escaneo masivo.
Herramienta de Explotación de Path Traversal en get_page_template() / locate_template() de WordPress Core
Solo para pruebas de seguridad autorizadas. El acceso no autorizado a sistemas informáticos es ilegal.
| Elemento | Detalles |
|---|---|
| ID de CVE | CVE-2026-87902 |
| ID de GHSA | GHSA-7hp8-65ch-5whp |
| Tipo de Vulnerabilidad | CWE-98 — Control Inadecuado del Nombre de Archivo para Include/Require |
| CVSS v3.1 | 8.1 (Alta) / CVSS 4.0: 9.2 (Crítica) |
| Componente Afectado | WordPress Core |
| Versiones Afectadas | 4.7.0 hasta 7.1.1 (todas las ramas) |
| Versiones Corregidas | 7.1.2 (y backports hasta 4.7.37) |
| Autenticación Requerida | Ninguna (No Autenticada) |
| Vector de Ataque | Una única solicitud GET |
| Descubierto Por | Robert Ressl (a través del programa HackerOne de WordPress) |
| Fecha de Divulgación | 22 de septiembre de 2026 |
| Explotado en la Naturaleza | Sí — incluido en el catálogo CISA KEV |
CVE-2026-87902 es una vulnerabilidad de path traversal e inclusión de archivo local (LFI) no autenticada en WordPress Core que afecta a todas las versiones de WordPress publicadas desde 2016 (4.7.0 a 7.1.1). Un atacante no requiere cuenta ni autenticación. Mediante la manipulación de un parámetro de consulta pagename malicioso, el atacante puede provocar que el mecanismo de resolución de plantillas de página de WordPress incluya cualquier archivo .php legible fuera del directorio del tema activo. Bajo condiciones específicas del servidor (PHP register_argc_argv = On y un pearcmd.php legible), la vulnerabilidad puede escalarse a ejecución remota de código (RCE).
| Rama | Versión Corregida |
|---|---|
| 4.7.x | 4.7.37 |
| 5.0.x | 5.0.29 |
| 5.3.x | 5.3.25 |
| 5.9.x | 5.9.18 |
| 6.0.x | 6.0.16 |
| 6.6.x | 6.6.9 |
| 6.9.x | 6.9.9 |
| 7.0.x | 7.0.6 |
| 7.1.x | 7.1.2 |
La vulnerabilidad reside en get_page_template() en wp-includes/template.php. Cuando la variable de consulta pagename está presente, la función construye page-{$pagename}.php pero no llama a validate_file() sobre ese valor para comprobar si hay directory traversal. El nombre de archivo candidato se pasa entonces a locate_template(), que lo concatena con la ruta del directorio del tema y solo comprueba file_exists() — no verifica que la ruta resuelta permanezca dentro del directorio del tema. Un nombre de plantilla que contenga ../ puede, por tanto, resolverse a un archivo PHP legible fuera del tema activo y ser incluido y ejecutado.
GET /?page_id=&pagename= → WP_Query resolves page_id, matches a published page (avoids 404) → get_page_template() urldecode()s pagename, builds page-{$pagename}.php → locate_template() concatenates candidate to theme directory, resolves via file_exists() → template-loader executes realpath() + include
WordPress aplica sanitize_title_for_query() a pagename, que reemplaza los puntos literales (.) por guiones (-) para bloquear el traversal. Opera sobre la entrada ya decodificada una vez y no decodifica recursivamente. El atacante envía %252e%252e%252f (../ doblemente codificado):
%252e → %2e, %252f → %2fsanitize_title_for_query() ve %2e%2e%2f (sin puntos literales) y lo deja pasarget_page_template() llama internamente a urldecode() de nuevo: %2e%2e%2f → ../page- (por ejemplo, page-templates/).page_id..php (WordPress añade la extensión).Nota sobre Hosts Windows: Win32 normaliza .. léxicamente, por lo que el traversal puede funcionar incluso si el directorio page- no existe. En Linux, ese directorio debe existir realmente.
Condiciones:
register_argc_argv está establecido en Onpearcmd.php legible en el servidorEl atacante incluye pearcmd.php mediante LFI y abusa de su comando config-create para escribir un archivo PHP en el servidor, y luego incluye ese archivo de nuevo mediante LFI para ejecutar comandos arbitrarios.
CVE-2026-87902 fue descubierta y reportada por Robert Ressl, un investigador de seguridad radicado en Suiza.
Reportada a través del programa HackerOne de WordPress en julio de 2026. El Equipo de Seguridad de WordPress coordinó la corrección y la publicó junto con WordPress 7.1.2 el 22 de septiembre de 2026.
| Fecha | Evento |
|---|---|
| Julio de 2026 | Robert Ressl reporta la vulnerabilidad a través del programa HackerOne de WordPress |
| 22 de septiembre de 2026 | Se publica WordPress 7.1.2 con la corrección; se publica el aviso |
| 22 de septiembre de 2026 | Se publican parches de seguridad para las ramas 7.0 a 4.7 |
| 23 de septiembre de 2026 | Los atacantes comienzan a sondear sitios vulnerables |
| 25 de septiembre de 2026 | CISA añade CVE-2026-87902 al catálogo KEV |
| Característica | Descripción |
|---|---|
| Huella de versión | Identifica la versión de WordPress mediante meta generator, feed RSS, OPML, readme.html, ?ver= de los recursos |
| Veredicto inteligente de versión | Utiliza el mapeo de versiones corregidas para determinar si el objetivo está en el rango afectado |
| Descubrimiento de temas | Extrae el slug del tema activo, detecta el tema padre, descubre directorios page-* |
| Descubrimiento de ID de página | Encuentra IDs de página válidos mediante la API REST, la clase del body page-id-, enlaces cortos |
| Validación del oráculo LFI | Utiliza archivos seguros como wp-links-opml.php y wp-trackback.php como oráculos con controles negativos |
| Travesía con doble codificación | Codifica automáticamente dos veces en porcentaje / y . para eludir sanitize_title_for_query() |
| Explotación de RCE mediante PEAR | Prueba rutas PEAR comunes, escribe y ejecuta archivos marcadores mediante config-create |
| Escaneo masivo | Escaneo concurrente multihilo de listas de objetivos |
| Salida de resultados | Persiste los resultados en vuln_lfi.txt y vuln_lfitorce.txt |
pip install requests
python3 CVE-2026-87902.py
Menú interactivo:
[1] Single Scan LFI [2] Single Scan LFI + RCE [3] Mass Scan LFI [4] Mass Scan LFI + RCE [5] Exit
Elija [1], introduzca la URL del objetivo:
url > https://target.example.com
Elija [2], introduzca la URL y el comando (por defecto id):
url > https://target.example.com cmd > id
Elija [3] o [4], introduzca el archivo que contiene las URL de los objetivos (una por línea, # para comentarios):
file > targets.txt
| Archivo | Contenido |
|---|---|
| vuln_lfi.txt | Objetivos con LFI confirmado |
| vuln_lfitorce.txt | Objetivos con RCE exitoso |
TIMEOUT = 8 # Request timeout (seconds) THREADS = 200 # Concurrent threads for mass scanning USE_ALL_ORACLES = False # Use all oracles (more accurate but slower)