
Injection de template non authentifiée dans Atlassian Jira
4.4.x
5.x.x
6.x.x
7.0.x
7.1.x
7.2.x
7.3.x
7.4.x
7.5.x
7.6.x before 7.6.14 (the fixed version for 7.6.x)
7.7.x
7.8.x
7.9.x
7.10.x
7.11.x
7.12.x
7.13.x before 7.13.5 (the fixed version for 7.13.x)
8.0.x before 8.0.3 (the fixed version for 8.0.x)
8.1.x before 8.1.2 (the fixed version for 8.1.x)
8.2.x before 8.2.3 (the fixed version for 8.2.x)
set JVM_SUPPORT_RECOMMENDED_ARGS= dans le fichier ./bin/setenv.bat (ou son équivalent ./bin/setenv.sh sous Linux) pour pouvoir lancer le débogage à distanceset JVM_SUPPORT_RECOMMENDED_ARGS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
Remote JVM Debug avec host et port sur localhost:5005 et Command line aguments for remote JVM-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
Exécutez le fichier ./bin/config.bat (ou ./bin/config.sh sous Linux) et définissez « Jira home » sur votre répertoire jira home

Exécutez le fichier ./bin/start-jira.bat (ou ./bin/start-jira.sh sous Linux). Vérifiez que la version de Java est correcte et que les ports 8080 et 5005 sont libres, sinon le démarrage échouera !
Nous choisissons le mode privé

À cette étape, pensez à utiliser une adresse e-mail capable de recevoir des e-mails :)

Configurez et testez correctement la connexion

Sur http://localhost:8080/secure/admin/EditApplicationProperties!default.jspa, activez la fonctionnalité Contact Administrators Form

Je ne note ici que quelques points d'attention pour la construction ; vous pouvez consulter building jira from source
Après avoir lu Advisory, nous savons que ce bug se trouve dans ContactAdministrators et SendBulkMail (ce dernier, je le laisse de côté car il nécessite une authentification). J'ai donc commencé à tester la fonctionnalité ContactAdministrators et à intercepter la requête.

Je vois que la requête va vers /secure/ContactAdministrators.jspa, alors je consulte le fichier ./atlassian-jira/WEB-INF/web.xml pour voir vers quelle classe cette requête est dirigée.


La requête est donc traitée par JiraWebworkActionDispatcher ; j'ai donc placé un point d'arrêt dans init et server de cette classe et j'ai lancé le débogage.

Le programme s'arrête alors dans la fonction server ; en suivant le flux, il entre dans ContactAdministrators.doExecute().

Ensuite, via send, le programme liste les comptes administrateur actifs.

Puis le programme passe par la fonction sendTo. On voit ici qu'il crée un MailQueueItem et l'ajoute à mailQueue.

Le programme appelle la fonction EmailBuilder.withSubject. Ici, la chaîne du sujet de l'e-mail (envoyée par l'attaquant) est convertie de String en TemplateSources et assignée au paramètre subjectTemplate de EmailBuilder.

Dans la fonction renderLater, le programme crée un EmailRenderer et l'utilise pour créer un RenderingMailQueueItem.

À partir de là, en revenant à la fonction ContactAdministrators.sendTo : après avoir créé un MailQueueItem, le programme ajoute l'élément à mailQueue puis revient à doExecute pour faire une redirection. En suivant ce flux de débogage, on ne peut pas atteindre la partie où le programme effectue le rendu de l'e-mail, donc on ne peut pas arriver au moment où l'injection de template se produit. Alors, comment faire pour suivre le traitement de l'e-mail ???
Je remarque que EmailRenderer possède une fonction renderNow (le programme n'appelle que renderLater) ; je suppose que lorsque l'e-mail en file d'attente est appelé pour être rendu, il suit le même flux que renderNow. J'ai donc décidé de tracer à partir de renderNow.

Depuis renderNow, le programme appelle EmailRenderer.render(). J'ai placé un point d'arrêt ici et renvoyé la requête pour voir si le programme passe réellement par là.

Heureusement, le programme a bien suivi la direction que j'avais prévue. Ensuite, il appelle renderEmailSubject.

Ensuite, le programme appelle DefaultVelocityTemplatingEngine.render(this.subjectTemplate).

On arrive à DefaultVelocityTemplatingEngine.applying et DefaultVelocityTemplatingEngine.asPlainText.

On continue avec l'appel à asPlainText(Writer writer).

On arrive à toWriterImpl ; comme le writer que je fournis est un Fragment, le programme saute dans le else.
private void toWriterImpl(Writer writer, boolean attachCartridge) throws IOException {
if (this.source instanceof File) {
File template = (File)this.source;
if (attachCartridge) {
this.context.attachEventCartridge(DefaultVelocityTemplatingEngine.this.createDefaultCartridge());
}