
Avis de sécurité détaillé pour CVE-2026-36669 : téléchargement arbitraire de fichiers sans authentification dans Feng Office, permettant un XSS stocké et un détournement de session. Comprend une analyse technique, un PoC et des étapes de correction.
Une vulnérabilité de téléchargement arbitraire de fichier non authentifié existe dans ck_upload_handler.php dans Feng Office Community Edition (version 3.11.13.11). Cette faille permet à des attaquants distants non authentifiés de télécharger des fichiers arbitraires (y compris des scripts .html ou .php malveillants) dans un répertoire accessible via le web. Combinée à l'absence de protections des cookies administratifs (HttpOnly), cette vulnérabilité peut entraîner un Cross-Site Scripting stocké (XSS) et un détournement de session administrative.
| Métrique | Détails |
|---|
| Identifiant CVE | CVE-2026-36669 |
| Type de vulnérabilité | Téléchargement illimité de fichier avec un type dangereux (CWE-434) |
| Faiblesse associée | Authentification manquante pour une fonction critique (CWE-306) |
| Produit affecté | Feng Office Community Edition |
| Versions affectées | Version 3.11.13.11 (et potentiellement les versions antérieures) |
| Statut d'exploitation | Preuve de concept vérifiée |
| Statut de correction | Non corrigé (Fournisseur notifié, aucun correctif fourni dans la fenêtre de divulgation standard) |
Le point de terminaison ck_upload_handler.php agit comme un script autonome. Il ne charge ni n'hérite du middleware d'authentification ni des listes de contrôle d'accès (ACL) de l'application principale. Par conséquent, toute demande externe envoyée directement à ce script est traitée comme authentifiée.
Dans le code source de ck_upload_handler.php, la logique de validation côté serveur des fichiers (lignes 21–25) conçue pour restreindre les téléchargements à des formats d'image spécifiques (.jpg, .png, .gif) a été explicitement commentée :
// $pattern = "/\.(jpg|png|gif)$/i";
// if (!preg_match($pattern,$_FILES['upload']['name'])) {
// ...
// }
Parce que cette contrainte regex est inactive, le mécanisme de téléchargement de fichiers accepte toute extension fournie par l'utilisateur.
Le script utilise la fonction PHP copy() pour écrire les fichiers téléchargés directement dans le répertoire /tmp/, qui est configuré pour être accessible via le web.
Le fichier de configuration globale application/config/config.php n'impose pas le drapeau HttpOnly sur les cookies de session. Lorsqu'un attaquant télécharge un fichier .html contenant des blocs de scripts côté client, tout administrateur qui visualise le fichier exécutera le script dans le contexte de sa session active. Cela permet aux attaquants d'extraire silencieusement les jetons de session administrative actifs.
Avis : Cette preuve de concept est fournie à des fins éducatives et d'audit défensif uniquement.
Pour vérifier la vulnérabilité, envoyez une requête POST multipart contenant un fichier de vérification inoffensif (par exemple, test.html) au point de terminaison, en ajoutant le paramètre CKEditorFuncNum requis :
curl -i -X POST \
-F "[email protected]" \
"http://<target-domain>/ck_upload_handler.php?CKEditorFuncNum=1"
Où test.html contient un balisage HTML de base de preuve de concept :
<!DOCTYPE html>
<html>
<body>
<script>
alert("Vulnerability Verified: " + document.cookie);
</script>
</body>
</html>
Si vulnérable, le serveur répondra avec un statut 200 OK et produira un bloc JavaScript indiquant le chemin de téléchargement :
<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction("1", "/tmp/test.html", "");
</script>
Si vous exécutez une version affectée de Feng Office, appliquez les correctifs manuels suivants pour sécuriser le point de terminaison de téléchargement de fichiers :
Assurez-vous que ck_upload_handler.php vérifie l'existence de sessions administratives actives avant de traiter toute logique de téléchargement de fichier.
Décommentez et appliquez strictement les vérifications d'extension. Rejetez tout téléchargement qui ne correspond pas explicitement aux types MIME d'image non exécutables attendus :
$pattern = "/\.(jpg|jpeg|png|gif)$/i";
if (!preg_match($pattern, $_FILES['upload']['name'])) {
header("HTTP/1.1 403 Forbidden");
exit("Invalid file type.");
}
Modifiez votre configuration PHP ou la configuration d'amorçage de l'application pour vous assurer que les cookies de session ne sont pas accessibles via les API de script côté client :
session.cookie_httponly = On
Soufiane LAGZIRI