
MISP <= 2.5.27 - Cross-Site Scripting stocké via Workflow Engine (Injection de template doT.js).
MISP <= 2.5.27 - Cross-Site Scripting stockée via le moteur de Workflow (injection de template doT.js)
Découverte par Franck FERMAN
Aperçu - Analyse de la cause racine - Chaîne d'attaque - Structure du projet - Utilisation - Remédiation - Références
CVE-2025-67906 (GCVE-1-2025-0031) est une vulnérabilité de Cross-Site Scripting (XSS) stockée dans MISP (Malware Information Sharing Platform) versions jusqu'à et y compris 2.5.27.
La vulnérabilité réside dans app/View/Elements/Workflows/executionPath.ctp, le composant d'affichage du chemin d'exécution des Workflows. Le champ name des déclencheurs (triggers) de workflow est persistant en base de données sans assainissement côté serveur, puis rendu dans le DOM via le moteur de template doT.js sans échappement HTML. Un attaquant authentifié peut injecter du HTML/JavaScript arbitraire qui s'exécute dans la session navigateur de tout utilisateur consultant le workflow compromis.
Comme la charge utile est stockée en base de données et rendue à chaque chargement de page, la XSS est persistante – elle survit aux rechargements de page, affecte plusieurs utilisateurs et persiste jusqu'à ce que le workflow soit explicitement supprimé.
Découverte : Cette vulnérabilité a été identifiée et divulguée de manière responsable par Franck FERMAN.
Plusieurs évaluations CVSS existent pour cette vulnérabilité :
| Source | Score | Sévérité | Vecteur |
|---|---|---|---|
| NIST NVD | 9.0 | Critique | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H |
| GCVE (CIRCL) | 7.1 | Élevée | CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:H/VI:N/VA:N/SC:H/SI:H/SA:H |
| CNA (MITRE) | 5.4 | Moyenne | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
La divergence des scores reflète des évaluations différentes de la profondeur de l'impact. Le score NIST NVD (9.0) tient compte d'un impact total sur la Confidentialité, l'Intégrité et la Disponibilité, étant donné que la charge utile XSS s'exécute avec les privilèges de session de la victime, permettant l'exfiltration de données au niveau administrateur et la manipulation des workflows. Le score CNA (5.4) ne considère qu'un impact limité sur la C/I pour une XSS générique. Le score GCVE CVSS 4.0 (7.1) introduit des modificateurs d'Exigences d'attaque (Privilège) et d'Interaction Utilisateur Active.
Le Périmètre est Modifié dans toutes les évaluations car la charge utile de l'attaquant (injectée via l'API MISP) s'exécute dans un contexte de sécurité différent (la session navigateur de la victime).
Le moteur de Workflow de MISP permet aux utilisateurs authentifiés de créer et modifier des workflows via l'API REST. Le modèle de données du workflow inclut un composant trigger avec un champ name. Ce champ est :
doT.js est un moteur de templating JavaScript rapide. Il utilise {{= }} pour l'interpolation, ce qui n'échappe pas le HTML par défaut. L'éditeur de Workflow de MISP utilise doT.js pour afficher les métadonnées des déclencheurs (y compris le champ name) dans le DOM. Lorsque le champ name contient du HTML comme ``, le moteur de template l'insère comme HTML brut, et le navigateur exécute le JavaScript intégré.
La correction nécessite soit :
{{! }} qui échappe le HTMLPOST /workflows/edit/{id}
{
"Workflow": {
"id": "1",
"data": "{\"1\":{\"data\":{\"name\":\"\"}}}"
}
}
La valeur name dans le champ JSON data est le point d'injection. L'ensemble du graphe du workflow est sérialisé sous forme de chaîne JSON dans le corps de la requête.
La vulnérabilité est amplifiée par le choix architectural d'utiliser un moteur de template côté client (doT.js) pour afficher l'éditeur visuel de workflow. L'éditeur de Workflow est une interface graphique de glisser-déposer où chaque déclencheur/action est affiché comme un bloc visuel. Le champ name du déclencheur est rendu comme une étiquette à l'intérieur de ces blocs graphiques.
doT.js construit les composants visuels en générant des chaînes HTML à partir de templates et en les insérant dans le DOM. La syntaxe d'interpolation {{= }} produit une sortie non échappée – toute donnée interpolée dans le template est traitée comme du balisage, et non comme du texte. Si le même champ name était rendu via element.textContent (qui traite l'entrée comme du texte brut) ou via la syntaxe de sortie encodée {{! }} de doT.js, aucune XSS ne serait possible, quelle que soit l'entrée.
La surface d'attaque existe précisément parce que :
{{= }}) pour les performancesname est interprétée comme du HTML par le navigateurIl s'agit d'un motif de vulnérabilité courant dans les applications web qui utilisent des moteurs de template côté client pour construire des interfaces visuelles interactives : le besoin de rendu riche crée une relation de confiance implicite entre le template et ses sources de données, et toute entrée utilisateur non assainie qui atteint le template devient du code exécutable.
<script>Une balise <script> brute injectée via interpolation de template ne s'exécutera généralement pas dans ce contexte. Les navigateurs n'exécutent pas les éléments <script> insérés dans le DOM après l'analyse initiale de la page (via innerHTML ou équivalent). Les attributs de gestionnaire d'événements comme onerror, onload ou onmouseover sur des éléments HTML contournent cette restriction car ils déclenchent du JavaScript en ligne lorsque le navigateur traite les attributs de l'élément, indépendamment de la façon dont l'élément a été inséré.