
Guide pas à pas d'analyse et d'exploitation pour CVE-2019-3396, une vulnérabilité critique SSTI dans Confluence Server & Data Center, incluant le débogage et l'exécution de payloads RCE.
Produit affecté : Confluence Server & Data Center
Versions affectées : de 6.0.0 à 6.15.4
Sévérité : Critique (CVSS ~9.8)
Cause :
Confluence dispose du plugin Widget Connector (utilisé pour intégrer des vidéos et du contenu externe comme YouTube, Vimeo...).
Cette fonctionnalité ne contrôle pas correctement les entrées utilisateur, ce qui mène à une Server-Side Template Injection (SSTI).
Un attaquant peut envoyer un payload malveillant → Confluence effectue le rendu avec le moteur de templates Velocity → exécution de code sur le serveur.
https://www.atlassian.com/software/confluence/downloads/binary/atlassian-confluence-6.9.0.zip
https://nguyendt.hashnode.dev/confluence-cve-2019-3396




Widget Connector, essayons de le chercher dans le dossier source de Confluence
com.atlassian.confluence.extra.widgetconnector.WidgetMacro.classDefaultRenderManager.class
getEmbeddedHtml() est utilisée
YoutubeRendererurl → le lien YouTube d’origine saisi par l’utilisateurparams → une map contenant les paramètres de configuration pour le rendu (par exemple : largeur, hauteur, template utilisé pour le rendu, etc.).
getEmbedUrl(), setDefaultParam() et DefaultVelocityRenderService.render()setDefaultParam()
Si _template n’existe pas → le template par défaut youtube.vm est assigné.
=> On peut donc ajouter soi-même _template au programme
Passons maintenant à DefaultVelocityRenderService.render()
Objectif de la méthode
Reçoit url + les paramètres params.
Utilise le template Velocity (.vm) pour générer le HTML intégré (iframe, embed, …).
Détermination du template
Si params contient _template → utilise ce template.
Sinon → utilise le template par défaut embed.vm.
Crée le contexte par défaut avec MacroUtils.defaultVelocityContext().
Ajoute tous les paramètres de params dans le contexte :
Si la clé est tweetHtml → le HTML est conservé tel quel.
Sinon → encodage sécurisé avec GeneralUtil.htmlEncode().
Ajoute urlHtml, width, height au contexte (s’ils sont vides, valeurs par défaut 400 × 300).

VelocityUtils.getRenderedTemplate()
getRenderedTemplate et getRenderedTemplateWithoutSwallowingErrors() sont appelées
getTemplate() est appelée
Ici, templateName correspond au _template mentionné plus haut.
Puis VelocityEngine.Template() est appelée

VelocityEngine, RunimeInstance.getTemplate() est ensuite appelée
RuntimeInstance (noyau Velocity)
C’est le « cœur » de Velocity Engine. Il s’occupe de :
Initialiser le moteur (init)
Gérer la configuration, les macros, le parser, les directives, les gestionnaires d’événements…
Et surtout : gérer les ressources via ResourceManager
→ Autrement dit, RuntimeInstance ne charge pas lui-même les ressources, mais délègue cette tâche à resourceManager.
CompatibleVelocityResourceManager.getResource() est appelée
ConfigurableResourceManager (personnalisé par Confluence)
C’est une implémentation de l’interface ResourceManager.
Il est responsable de :
Gérer les resource loaders (file loader, classpath loader, URL loader…).
Gérer le globalCache (cache des templates selon resourceKey).
Charger/actualiser le template (fichier .vm) lorsque RuntimeInstance le demande.

try {
this.refreshResource(resource, encoding);
} catch (ResourceNotFoundException var7) {
this.globalCache.remove(resourceKey);
return this.getResource(resourceName, resourceType, encoding);
}
Lorsqu’une ressource est dans le cache, elle n’est pas renvoyée immédiatement : refreshResource(...) est appelé.
refreshResource compare la date de dernière modification sur le disque avec celle du cache.
Si le fichier a changé → la ressource en cache est invalidée → rechargée depuis le disque → le cache est mis à jour.