Résumé
Lors d’un test d’intrusion en boîte noire, une instance d’EzGED3(1) exposée sur Internet est découverte. L’application présente des failles de sécurité critiques permettant une compromission complète du compte administrateur sans authentification préalable (CVE-2025-51539). Le listing de répertoire est activé sur un dossier accessible publiquement, révélant des fichiers contenant des informations sur l’implémentation interne de l’application. L’un de ces fichiers référence un script PHP permettant la lecture arbitraire de fichiers en raison de l’absence de contrôles d’accès et de validation des entrées.
Des fichiers sensibles, incluant les identifiants de connexion à la base de données, deviennent accessibles. Cet accès conduit à des scénarios d’élévation de privilèges, avec la récupération de données utilisateurs, de jetons de réinitialisation administrateur, et de hachages de mots de passe faibles (CVE-2025-51540).
Version vulnérable < 3.5.72.27183

Write-up
1. Découverte initiale : Listing de répertoire
Lors de la phase de reconnaissance initiale, il est observé que le listing de répertoire est activé sur le chemin /data/
path. L’accès à https://<target>/data/
renvoie un index brut des fichiers et sous-répertoires présents à cet emplacement. Parmi les fichiers listés, on trouve plusieurs fichiers .html
et .php
.

Un fichier HTML en particulier (ezOpenFile.html
) contient du code PHP intégré qui n’est pas exécuté par le serveur. En conséquence, le code source brut s’affiche dans le navigateur, exposant la logique interne de l’application, ainsi qu’une ligne particulièrement intéressante :
<a class="MenuItem" href="showparaphdocs.php?download=0&path='.$path.'">[Cliquez ici pour afficher le document]</a>
Le fichier showparaphdocs.php
peut être utilisé pour afficher un fichier (download=0
) ou le télécharger (download=1
).
2. Contournement de l’authentification
L’étape suivante consiste à tenter de lire le fichier PHP identifié précédemment dans le listing de répertoire, puisqu’il est confirmé comme existant et pourrait révéler le fonctionnement du script. À la lecture du code source, il apparaît clairement qu’aucune authentification n’est réellement appliquée.

Le script vérifie si les paramètres sessionid
ou token
sont présents, mais comme ils ne le sont pas, la condition échoue silencieusement et le reste du code s’exécute malgré tout.
if(isset($_REQUEST["token"],$_REQUEST["sessionid"])) {
if($_REQUEST["token"] == "<redacted>") {
$sessionid = $_REQUEST["sessionid"];
$params = Authentication::authenticate(array("sessionid" => $sessionid));
if(!$params) {
die("Requested authentication by session failed.");
}
}
}
Ce bloc de code n’est exécuté que si les deux paramètres token
et sessionid
sont présents dans la requête. Si l’un des deux est absent, l’ensemble du bloc est ignoré, y compris la logique d’authentification.
Dans le code, la valeur du paramètre path
est utilisée directement dans un appel à @readfile($path)
sans aucune validation ni restriction. Cette fonction demande à PHP de lire le fichier spécifié par $path
depuis le système de fichiers du serveur et d’en afficher directement le contenu dans la réponse HTTP. En l’absence de toute vérification sur le chemin fourni, il est possible d’effectuer des attaques de type path traversal, par exemple en fournissant ../../../../etc/passwd
, ou en ciblant des fichiers applicatifs tels que config.php
, des dumps de base de données, ou d'autres ressources sensibles.
L'application pouvant être déployée aussi bien sur des serveurs Windows que Linux, le comportement dépendra du système d'exploitation utilisé.
Pour extraire l'intégralité du code source d’un dossier, on peut utiliser la commande one-liner suivante :
for i in $(cat files.txt); do
curl -k -s "https://<ip>/data/showparaphdocs.php?download=0&path=$i" > $i;
done
3. Accès à la base de donnée
Lors de l’analyse du contenu des fichiers, une référence à un fichier de configuration local est identifiée :
nchp/etc/nchp/ezged/instance.conf
Ce fichier contient des informations sensibles liées à la configuration de la base de données, notamment :
-
Le nom d’hôte de la base de données
-
Le nom d’utilisateur et le mot de passe associés
-
Le nom de la base de données utilisée par l’application
Sur certains serveurs, une interface phpMyAdmin est exposée publiquement. Les identifiants extraits depuis le fichier de configuration permettent alors de se connecter directement en tant qu’utilisateur root, donnant un accès complet à toutes les données de l’application, y compris aux mots de passe hachés stockés dans les tables internes.
Astuce intéressante : lecture directe des fichiers de données MySQL
Avec les informations suivantes:
… il devient alors possible de lire directement les fichiers de stockage bruts utilisés par MySQL pour persister les données des tables.
MySQL stocke ses données (selon la configuration) dans la structure suivante :
mysql/data/<database_name>/<table_name>.<extension>
Les extensions de fichiers pertinentes incluent : .ibd
, .frm
, .myd
, .opt
, .sql
, et .cnf
.
Dans ce cas, la table responsable du stockage des utilisateurs et des hachages de mots de passe se nomme _secusr
, et, avec le format de stockage InnoDB, cette table correspond au fichier suivant :
mysql/data/<database_name>/_secusr.ibd
En récupérant ce fichier via la vulnérabilité de lecture arbitraire, on obtient un dump brut de la table des utilisateurs.

Le contenu brut du fichier est suffisant pour extraire les identifiants des utilisateurs. Dans EzGED3, les mots de passe sont stockés en utilisant la construction faible md5(md5(password))
, qui offre une protection très limitée contre les attaques hors ligne par force brute.
Cependant, dans ce cas précis, il n’est même pas nécessaire de casser les hachages pour obtenir un accès administrateur complet.
L’application propose un mécanisme de réinitialisation de mot de passe. Les jetons utilisés pour cette procédure sont stockés dans le même fichier.
Une fois un jeton valide récupéré, il devient possible d’initier une réinitialisation du mot de passe sans connaître le mot de passe actuel ni avoir accès à l’adresse e-mail de l’administrateur.
Ce contournement permet une prise de contrôle complète du système, uniquement par lecture de fichiers, sans recours à une attaque par force brute ni à une élévation de privilèges par exécution de code.
Timeline
- 2024-11-14 – Découverte de la vulnérabilité
- 2024-11-15 – Signalement de la vulnérabilité à l’éditeur
- 2024-12-05 – Validation du rapport par EZDEV
- 2025-02-17 – Relance / suivi
- 2025-05-16 – Déclaration de la CVE
- 2025-08-13 – Publication de l’article
Resources
- (1) https://www.ezged.org