Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2021-39115 — Template-Injection in E-Mail-Vorlagen führt zur Codeausführung auf dem Jira Service Management Server | Kitploit
Tools/GitHubGitHub/petrusviet/cve-2021-39115
SchwachstellenanalyseCode-AnalyseExploitationWebanwendungs-ExploitationPenetrationstestsLernen & Bildung
GitHubpetrusviet/cve-2021-39115

CVE-2021-39115

Template-Injection in E-Mail-Vorlagen führt zur Codeausführung auf dem Jira Service Management Server

Repository anzeigen
48121vor 5 JahrenVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2021-39115

Template-Injection in E-Mail-Vorlagen führt zur Codeausführung auf Jira Service Management Server

I) Aufbau

Ich habe das Deployment + Debugging hier beschrieben, ihr könnt es dort nachschlagen.

II) Analyse

In der Beschreibung dieser CVE wird klar gesagt, dass der Bug in der Funktion Email Template liegt. Mit Admin-Rechten kann der Benutzer die Vorlagen der Benachrichtigungs-E-Mails beliebig ändern. Dieser Bug erfordert Admin-Rechte, ist also trotz RCE nicht besonders kritisch, aber ich habe beschlossen, den Blog einfach zum Spaß zu schreiben :) wer sich mit SSTI beschäftigt, kann es sich ansehen.

  • Um zur Sache zu kommen, ich habe die Version atlassian-jira-servicedesk-4.17.0-m0006-standalone deployed und per Diff versucht herauszufinden, was sich gegenüber der Version 4.18.0 geändert hat: image

Als ich diesen Haufen sah, ... natürlich habe ich nicht jede Datei einzeln gelesen, ich bin zu faul. Spaß beiseite, abgesehen vom zusätzlichen Security-Fix enthalten die Versionen auch Upgrades und Änderungen an Funktionen. Alles zu diffen und dann durchzulesen ist sehr zeitaufwändig. In einigen Fällen muss ich das wohl tun, aber in diesem Fall habe ich es nicht gemacht =)))

  • Wie oben erwähnt, kann der Admin die Vorlagen aller Benachrichtigungs-E-Mails im System ändern. Deshalb muss ich als ersten Schritt wissen, welche Kontexte es beim Parsen der Benachrichtigungs-E-Mails gibt? Das ist besonders wichtig, wenn man einen SSTI-Bug (mit Sandbox) ausnutzen will. Der effektivste Weg ist, per Debugging in den Teil zu springen, der die E-Mail-Vorlagen parst, um den Wert der Kontextvariablen zu sehen.
  • Natürlich gibt es viele verschiedene Arten von Benachrichtigungen (Registrierung, Passwort ändern, ...), jede verwendet einen anderen Endpoint. Ich nutze die Funktion SendBulkMail, um eine Benachrichtigungs-E-Mail zu erzeugen. Auf den Stack Call dieses Endpoints möchte ich nicht näher eingehen, um es kurz zu halten, da er ähnlich zum Stack Call in CVE-2019-11581 ist.

In der Funktion SimpleNote.render kann ich die Kontextvariable ansehen, um zu sehen, was ich ausnutzen kann:

Nach meiner eigenen Erfahrung achte ich darauf, Kontexte/Klassen mit Schlüsselwörtern wie: Utils, Manager, service, ... zu überprüfen. Mir ist aufgefallen, dass der Kontext $jirautils (Klasse com.atlassian.jira.util.JiraUtils) eine Methode public static <T> T loadComponent(String className, Class<?> callingClass) enthält:

Ich habe die Doku durchforstet, um zu sehen, was sie tut und wie sie verwendet wird, denn die Eingabe ist ein String className und die Ausgabe ist eine Klasse, also könnte diese Methode möglicherweise beliebige Klassen laden:

  • Wie die Doku sagt, dient diese Funktion zum Laden von Klassen :) Ich habe mich sofort daran gemacht zu prüfen, ob die Methode wirklich beliebige Klassen laden kann:

Ich gehe zu System -> Email templates und lade die aktuelle Template-Datei herunter

Es gibt viele verschiedene Vorlagen, jede für eine andere Art von Benachrichtigung, also habe ich nach einer Datei gesucht, die für viele verschiedene Benachrichtigungsarten gemeinsam verwendet werden kann, z. B. email\html\includes\header.vm

Nachdem ich die bearbeitete Template-Datei hochgeladen und mit SendBulkMail eine Benachrichtigungs-E-Mail gesendet hatte, erhielt ich in der E-Mail folgende Ausgabe:

Im Grunde hat diese Klasse keine Konstruktoren oder wird nicht akzeptiert. Ich habe es mit einer anderen Klasse versucht, die Konstruktoren hat (Konstruktoren ohne Eingabe):

Und das Ergebnis war wie erwartet. Ich konnte die Klasse erfolgreich abrufen:

  • Damit können wir also Klassen nahezu beliebig laden, das ist schon ganz gut. Aber wie kommt man zu RCE ??? Jira verwendet Velocity-Templates und eine ziemlich vollständige Sandbox mit Blacklist-Paketen und Blacklist-Klassen (bei Blacklist-Klassen können alle Klassen blockiert werden, die von den Klassen in der Blacklist erben). Die Verwendung von öffentlich im Internet verfügbaren Klassen ist fast unmöglich. An diesem Punkt musste ich einen Diff zwischen der fehlerhaften Version und der Patch-Version durchführen, um zu sehen, wie sie sich unterscheiden. Natürlich diff ich nicht alles, sondern nur die Konfigurationsdatei von Velocity (\atlassian-jira\WEB-INF\classes\velocity.properties), um zu sehen, ob es Aktualisierungen gibt:

Wir sehen, dass 3 Klassen zur Blacklist hinzugefügt wurden:

root@kitploit:~
org.springframework.expression.spel.standard.SpelExpressionParser,\
com.atlassian.jira.component.ComponentAccessor,\
com.atlassian.jira.plugin.ComponentClassManager

Als ich die einzelnen Klassen geprüft habe, stellte ich fest, dass die Klasse SpelExpressionParser eine Funktion public SpelExpression parseRaw(String expressionString) hat. Nach kurzer Google-Recherche zur Verwendung sieht es ungefähr so aus:

root@kitploit:~
#set($SpelExpressionParser = $jirautils.loadComponent('org.springframework.expression.spel.standard.SpelExpressionParser',$i18n.getClass()))
$SpelExpressionParser.parseRaw("T(java.lang.Runtime).getRuntime().exec('calc')")

Wie ihr seht, gibt die Funktion parseRaw ein Objekt der Klasse org.springframework.expression.spel.standard.SpelExpression zurück, rendert den übergebenen Ausdruck aber noch nicht wirklich. Ich bin in die Klasse SpelExpression gesprungen und habe die Methode getValue gefunden:

root@kitploit:~
@Nullable
    public Object getValue() throws EvaluationException {
        CompiledExpression compiledAst = this.compiledAst;
        if (compiledAst != null) {
            try {
                EvaluationContext context = this.getEvaluationContext();
                return compiledAst.getValue(context.getRootObject().getValue(), context);
            } catch (Throwable var4) {
                if (this.configuration.getCompilerMode() != SpelCompilerMode.MIXED) {
                    throw new SpelEvaluationException(var4, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION, new Object[0]);
                }
            }

            this.compiledAst = null;
            this.interpretedCount.set(0);
        }

        ExpressionState expressionState = new ExpressionState(this.getEvaluationContext(), this.configuration);
        Object result = this.ast.getValue(expressionState);
        this.checkCompile(expressionState);
        return result;
    }

Beim Blick auf Input/Output habe ich als jemand, der auf sein Bauchgefühl vertraut, beschlossen, es einfach auszuprobieren, statt weiter in die Doku zu schauen:

root@kitploit:~
#set($SpelExpressionParser = $jirautils.loadComponent('org.springframework.expression.spel.standard.SpelExpressionParser',$i18n.getClass()))
$SpelExpressionParser.parseRaw("T(java.lang.Runtime).getRuntime().exec('calc')").getValue()

und das Ergebnis:

III) Fazit

Damit konnten wir die Sandbox von Velocity umgehen und RCE erreichen. Wenn ich mich jedoch in die Lage des Autors versetze – der Person, die diesen Bug entdeckt hat – gibt es noch viele Fragen, die ich nicht beantworten kann:

  • Warum wurden bis zu 3 Klassen zur Blacklist hinzugefügt?

Als ich diese 3 Klassen untersuchte, sah ich, dass sie eine Kette bilden können:

root@kitploit:~
ComponentAccessor.getComponentClassManager() 
  => ComponentClassManager.newInstance(String className) (Class này có thể load class tùy ý)
        => SpelExpressionParser

Wenn der Autor wie ich $jirautils verwendet, bräuchte er die anderen beiden Klassen nicht. Aber wenn der Autor $jirautils nicht verwendet, wie kommt er dann an ComponentAccessor???

  • Wie konnte der Autor die oben genannten 3 Klassen finden? Das ist die Frage, die mich am meisten beschäftigt und die ich am liebsten beantwortet hätte, aber vielleicht erfahre ich es nur, wenn ich den Autor direkt kontaktiere. Schade, dass ich nicht weiß, wer der Autor dieses Bugs ist.

IV) Den Patch weiterhin umgehen

Tool herunterladen