Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
cve-2026-87902-wordpress-lfi-lab — Laboratorio de reproducción + escáner de lista de URL + PoC para CVE-2026-87902 / GHSA-7hp8-65ch-5whp — LFI no autenticado en get_page_template() de WordPress a RCE condicional (WP 4.7.0-7.1.1, corregido en 7.1.2). Pruebas autorizadas/defensivas. | Kitploit
Herramientas/GitHubGitHub/dinosn/cve-2026-87902-wordpress-lfi-lab
Escáneres de VulnerabilidadesEscáneres de Vulnerabilidades WebAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebPruebas de PenetraciónAprendizaje y Educación
Desarrollo de Payloads
Labs y Práctica
GitHubdinosn/cve-2026-87902-wordpress-lfi-lab

cve-2026-87902-wordpress-lfi-lab

Laboratorio de reproducción + escáner de lista de URL + PoC para CVE-2026-87902 / GHSA-7hp8-65ch-5whp — LFI no autenticado en get_page_template() de WordPress a RCE condicional (WP 4.7.0-7.1.1, corregido en 7.1.2). Pruebas autorizadas/defensivas.

Ver Repositorio
13144hace 26 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-87902 / GHSA-7hp8-65ch-5whp — LFI no autenticado en get_page_template() de WordPress → RCE condicional

Laboratorio de reproducción + escáner de listas de URL + PoC, construido y validado de extremo a extremo contra WordPress genuino 7.1.1 (vulnerable) y 7.1.2 (parcheado) en el laboratorio Docker.

  • Aviso: https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-7hp8-65ch-5whp
  • Tipo: CWE-98 control inadecuado del nombre de archivo para include/require (path traversal → inclusión local de PHP)
  • Afectados: WordPress 4.7.0 – 7.1.1 (corregido en 7.1.2 y backports por rama: 7.0.6, 6.9.9, 6.8.10 … hasta 4.7.37)
  • Auth: ninguna. CVSS 4.0: 9.2 (AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H)
  • Precondiciones: (1) el tema activo tiene un directorio de nivel superior llamado page-* (p. ej. page-templates/ — presente en Twenty Twelve, Twenty Fourteen, Neve, Hestia, Sydney); (2) solo para RCE: un pearcmd.php legible y register_argc_argv=On.

1. Causa raíz (verificada contra el código fuente de 7.1.1 vs 7.1.2)

wp-includes/template.php :: get_page_template() construye un candidato de plantilla a partir de la query var pagename controlada por el atacante sin validate_file():

// WordPress 7.1.1 (VULNERABLE)
if ( $pagename ) {
    $pagename_decoded = urldecode( $pagename );
    if ( $pagename_decoded !== $pagename ) {          // <-- no validate_file()
        $templates[] = "page-{$pagename_decoded}.php";
    }
    $templates[] = "page-{$pagename}.php";
}
// WordPress 7.1.2 (PATCHED) — the guard the sibling $template branch already had, + realpath containment
if ( $pagename_decoded !== $pagename && 0 === validate_file( $pagename_decoded ) ) {
    $templates[] = "page-{$pagename_decoded}.php";
}
// plus new _wp_is_template_path_allowed() enforcing the resolved path stays inside a theme root

locate_template() luego hace file_exists($theme_dir . '/' . $candidate) e include del archivo encontrado. Como el candidato es page-{...}.php, el payload debe continuar un directorio de tema real que comience con page- (p. ej. page-templates/) y luego salir con ../ hacia cualquier .php legible.

La doble codificación es obligatoria. get_query_var('pagename') ya está decodificado una vez por PHP, por lo que un ../ simple hace que urldecode($pagename) === $pagename y la rama vulnerable se omita. Un %252e%252e%252f doble-codificado sobrevive la primera decodificación como %2e%2e%2f y se convierte en ../ solo por el urldecode() extra — que es el bug.


2. Laboratorio (lab/)

Versiones genuinas en paralelo en el host Docker, que difieren solo por el parche de seguridad:

ServicioURL (solo loopback)WordPressRol
wp-vulnhttp://127.0.0.1:80917.1.1vulnerable
wp-patchedhttp://127.0.0.1:80927.1.2control parcheado
db—MySQL 8.4compartido (dos bases de datos)

Imagen base wordpress:php8.3-apache (que ya incluye pearcmd.php y register_argc_argv=On), con el core incluido reemplazado por los auténticos wordpress-7.1.1.zip / 7.1.2.zip. Twenty Fourteen está activado (con page-templates/ real), y también se crea un fixture page-templates/ en el tema activo. ID de página publicada = 2 (Sample Page).

# on the docker lab host
cd /tmp/cve-2026-87902-lab
./up.sh        # build + install both instances (idempotent)
./down.sh      # tear down + remove volumes

Los puertos se enlazan solo a 127.0.0.1 — la instancia vulnerable nunca queda expuesta a la red.


3. Escáner / PoC (poc/cve-2026-87902-scan.py)

Python 3, solo stdlib (sin pip install). Toma una lista de URLs y reporta cuáles son vulnerables. El escaneo por defecto es no destructivo: incluye el archivo core de solo lectura wp-links-opml.php y busca el documento OPML resultante — prueba de que la inclusión arbitraria de .php se disparó, sin escrituras ni cambios de estado.

# single URL
./cve-2026-87902-scan.py http://target/

# a list of your assets, JSON report, 20 workers
./cve-2026-87902-scan.py -f urls.txt --threads 20 --json report.json

# from stdin, only show vulnerable/possibly rows
cat urls.txt | ./cve-2026-87902-scan.py --stdin -q

Cómo se clasifica un objetivo

  1. Fingerprint de WordPress + versión (meta generator → feed <generator> → wp-links-opml.php → readme.html → asset /wp-includes/ ?ver=).
  2. Descubrir un ID de página publicada válido (REST /wp/v2/pages, fallback ?rest_route=, homepage page-id-N, por defecto page_id=2) — necesario para que la petición resuelva a una Page y se ejecute get_page_template().
  3. Barrido del oráculo OPML: para segment × depth (segmento por defecto templates, profundidades 4,3,5,6,7), enviar page_id=<id>&pagename=<../ doble-codificado → wp-links-opml> (POST, para esquivar la redirección canónica) y exigir un HTTP 200 que contenga <opml version="1.0"> + un marcador secundario estructural (</opml> / <outline / <dateCreated>).
  4. Control negativo (prueba de causalidad): ante un hit, reemitir la petición idéntica apuntando a un .php garantizado-inexistente. Si el OPML aún aparece, el OPML es ambiental (proxy / caché / app de feeds), no nuestra inclusión → degradado a POSSIBLY. Solo un hit cuyo control esté limpio es VULNERABLE.

Robustez: preserva rutas de subdirectorio (http://host/blog), maneja gzip/deflate y charsets inusuales, reintenta una sonda una vez ante error de transporte, descubre/valida IDs de página (REST → ?rest_route= → homepage → defaults), aplica un presupuesto de tiempo por objetivo, y nunca afirma NOT_VULNERABLE a partir de una fuente de versión de baja confianza (asset ?ver= / readme.html) — esas degradan a POSSIBLY.

VeredictoSignificado
VULNERABLEEl oráculo OPML se disparó — LFI confirmado (definitivo)
NOT_VULNERABLEVersión de rama parcheada, o versión fuera de 4.7.0–7.1.1
POSSIBLY_VULNERABLEVersión vulnerable/desconocida pero oráculo silencioso (probablemente sin directorio de tema page-*, diseño no estándar, o sin ID de página descubrible) — verificar manualmente
NOT_WORDPRESS / ERRORSin indicadores de WP / fallo de transporte

Código de salida: 2 si hay algún VULNERABLE, 1 si hay algún POSSIBLY (y ningún VULNERABLE), si no 0.

Flags útiles: --segments, --depths, --method {POST,GET,both}, --page-id, --max-pageids, --max-time (presupuesto por objetivo), --timeout, --threads, --proxy, --header, --insecure (TLS off — solo dev), --json, --jsonl. Para una instalación de WordPress en subdirectorio, pasar la base completa (p. ej. https://host/blog); para Bedrock/core-en-wp/ el barrido también prueba objetivos de oráculo con prefijo wp/.

Escalada a RCE (opt-in, uso en laboratorio)

./cve-2026-87902-scan.py http://target/ --verify-rce --i-have-authorization --page-id 2

Ejecuta la cadena PEAR pearcmd.php: la query string dividida por + lleva argv de config-create que escribe un marcador .php sin comillas bajo /tmp; una segunda petición lo incluye. Imprime el marcador ejecutado + php_uname() + uid. Escribe un archivo en el objetivo → un solo objetivo, requiere --i-have-authorization, desactivado por defecto.


4. Evidencia (evidence/)

Descargar herramienta