Log4Shell
Zuletzt aktualisiert mit Hinweisen zu Log4J2 Version 2.13.1 und 2.3.1 für Java 7 und Java 6 am 22.12.2021, 11:25. Davor aktualisiert mit Hinweisen zu CVE-2021-45105 und Absicherung mittels mod_security am 20.12.2021, 11:55.
Die Apache Software Foundation hat am 10.12.2021 ein kritisches Sicherheits-Problem in der Logging-Bibliothek Log4j veröffentlicht. Das zugehörige Problem hat den Namen „Log4Shell“ (mancherorts auch „Log4jShell“) und trägt die offizielle CVE-Nummer CVE-2021-44228. Weitere Untersuchungen an denen auch kippdata beteiligt war, resultierten in der Aufdeckung und Bekanntgabe der zusätzlichen Probleme CVE-2021-45046 und CVE-2021-45105.
Die offizielle Erläuterungsseite des Log4j-Projektes findet sich unter https://logging.apache.org/log4j/2.x/security.html. Die entsprechenden CVE-Seiten sind https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228, https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-45046 und https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-45046.
Die Auswirkungen der Probleme sind:
- Remote Code Execution (RCE), also die Möglichkeit eines Angreifers eigene Befehle und Programme auf das angegriffene System zu übertragen und dort zur Ausführung zu bringen
- Denial of Service (DoS), also die Möglichkeit das angegriffene System etwa durch Abstürze oder Überlastung disfunktional zu machen
- und Information Disclosure (ID), also die Fähigkeit nicht öffentliche Informationen aus einem System auszulesen.
Auch wenn RCE automatisch DoS und ID zur Folge hat, werden diese hier erwähnt, weil einige Gegenmaßnahmen zwar RCE unterbinden, jedoch nicht auch den DoS- oder ID-Angriff.
Das Problem hat zu Recht den höchsten CVSS Score 10.0.
Welche Software kann betroffen sein?
Jede Anwendung, die Log4j in einer Version vor 2.17.0 beinhaltet – das ist die Version, die am 18.12.2021 veröffentlicht wurde – mit Java 7 eine Version vor 2.13.3, muss als angreifbar gelten. Allerdings ist die vorherige Version 2.16.0 bereits gut gegen RCE geschützt und auch Angriffe vom Typ DoS und ID sind nur möglich, wenn die Log-Konfiguration bestimmte Eigenschaften hat. Außerdem wurden für den Einsatz mit Java 7 Version 2.12.2 und 2.12.3 veröfentlicht und für den Einsatz mit Java 6 Version 2.3.1. Versionen 2.12.3 und 2.3.1 sind so wie 2.17.0 vollständig geschützt, Version 2.12.2 so wie 2.16.0 nur eingeschränkt.
Eine weitergehende Prüfung, ob ein konkreter Einsatz einer anfälligen Version angreifbar ist, ist nur durch ein aufwendiges professionelles und dennoch nicht eindeutiges Penetration Testing möglich – oder alternativ durch ein extrem aufwendiges Source Code Review, das jede Log-Nachricht im Source Code der Anwendung und aller Hilfsbibliotheken untersucht.
Die Log4j-Bibliothek ist in der Programmiersprache Java geschrieben und wird in sehr vielen Java-Anwendungen verwendet. Auch Anwendungen in anderen Sprachen, die in einer Java Virtual Machine laufen, wie etwa Groovy, Scala, Kotlin oder Clojure können diese Bibliothek verwenden.
Das Problem hat auch deshalb den CVSS Score 10.0, weil die Voraussetzungen für einen effektiven Angriff grundsätzlich nicht hoch sind.
Die Bibliothek Log4j gibt es in 2 Versionen:
- Version 2.x ist die seit vielen Jahren gepflegte Versionslinie. Alle veröffentlichten Versionen vor Version 2.17.0 (ausgenommen einige Beta-Versionen, sowie die für den Einsatz mit Java 7 bzw. Java 6 neu veröffentlichten Versionen 2.12.3 und 2.3.1) sind angreifbar. Die letzte Woche veröffentlichten Versionen 2.16.0 bzw. 2.12.2 sind für die schlimmsten Szenarien nicht mehr angreifbar. Ein verbliebenes DoS-Szenario und eine schwache Form von ID wird jedoch erst mit den Versionen 2.17.0, 2.12.3 und 2.3.1 geschlossen.
- Version 1.2.x wird seit vielen Jahren nicht mehr weiter supportet und ist nur in stark abgeschwächter Fassung von diesem neuen Problem betroffen. Jedoch wurde für diese Version seit etlichen Jahren keine Sicherheitspflege mehr durchgeführt, so dass sie aus anderen Gründen als angreifbar gelten muss. Für Version 1.2.x gibt es einen einfachen Update-Pfad auf 2.x, der die sogenannte Bridge Log4j 1.2 auf 2.0 (Artefakt log4j-1.2-api.jar) verwendet. Auf Dauer sollte jedoch eine volle Migration durchgeführt werden, die entsprechende Source Code-Anpassungen der nutzenden Anwendung voraussetzt. Siehe hierzu die Seite https://logging.apache.org/log4j/2.x/manual/migration.html.
Wie steht es mit anderen Logging-Bibliotheken?
Nach aktuellem Stand sind die gängigen Logging-Fassaden und -Implementierungen SLF4J, Logback und java.util.logging nicht betroffen.
Wie finde ich heraus, ob meine Anwendungen wirklich betroffen sind?
Das schwerwiegendste Problem ist die Remote Code Execution in Versionen vor 2.16.0. Eine Prüfung kann grundsätzlich folgende Ansätze verwenden:
- Bei Standardsoftware Nutzung von Hersteller-Informationen und anderen öffentlichen Listen betroffener Software
- Source Code Review: Prüfung der Log-Konfiguration, aber vor allem auch aller Code-Stellen, die Log-Nachrichten erzeugen. Dies wäre nicht nur in der eigentlichen Anwendung, sondern auch allen Hilfsbibliotheken, die sie verwendet und die ggf. ebenfalls Log4j nutzen, notwendig. Dies ist nur mit erheblichen Aufwand möglich und wird deshalb in fast allen Fällen nicht effektiv sein.
- Penetration Testing: automatisierte Verwendung der Anwendung mit vielen unterschiedlichen – auch zufällig erzeugten – legitimen und falschen Daten. Ein für dieses Problem zuverlässiges Penetration Testing ist ebenfalls mit sehr hohem Aufwand verbunden und kann nur von Spezialisten sinnvoll durchgeführt werden.
Nach unserer Einschätzung muss deshalb bei jeder Anwendung, die Log4J verwendet von einer Angreifbarkeit ausgegangen werden, außer der Hersteller eine Anwendung schliesst dies für diese offiziell aus.
Das weitere DoS- und ID-Problem in Version 2.16.0 kann nur ausgenutzt werden, wenn eine verwundbare Log-Konfiguration verwendet wird. Bekannte Angriffsvektoren nutzen einen Eintrag der Form ${ctx:mykey} oder $${ctx:mykey} in einem PatternLayout in der Konfiguration. Diese können – sofern ein Angreifer Daten in den MDC (Mapped Diagnostic Context) einschleusen kann – zu einer unterminierten Rekursion und damit einem Denial of Service führen. Indirekt kann dieser DoS dann für ein Information Disclosure genutzt werden, indem ein Angreifer mit bestimmten Werten durchprobiert, wann ein DoS ausgelöst wird. Die alleinige Verwendung eines MDC, etwa via %X, %mdc oder %MDC, stellt jedoch kein Problem dar.
Gibt es Listen, welche Anwendungen betroffen sind?
Eine umfangreiche inoffizielle Liste findet sich unter https://gist.github.com/SwitHak/b66db3a06c2955a9cb71a8718970c592.
Das „Nationaal Cyber Security Centrum“ aus den Niederlanden pflegt aktuell eine Liste betroffener Software unter https://github.com/NCSC-NL/log4shell/. Dort gibt es verschiedene Kategorien, unter anderem die wichtige Liste https://github.com/NCSC-NL/log4shell/tree/main/software.
Die Apache Software Foundation (ASF) hat eine aktuelle Liste der von der ASF bereitgestellten Software mit Status unter https://blogs.apache.org/security/entry/cve-2021-44228 veröffentlicht.
Bitte beachten Sie, dass in den Listen als Beispiel häufig steht, dass Apache Tomcat nicht betroffen ist. Das ist grundsätzlich korrekt, weil Tomcat nicht zwingend mit Log4J2 für das Logging kommt. Viele Distributionen – wie etwa unsere – fügen jedoch Log4j 2 wegen seiner für professionelle produktive Umgebungen wichtigen Fähigkeiten hinzu, wodurch Tomcat angreifbar wird. Ähnliches mag auch für andere Software in den Listen gelten.
Seit wann ist das Problem bekannt?
Leider gibt es mittlerweile Hinweise, dass die ersten Versuche, die Lücke auszunutzen, etwa am 01.12.2021 geschahen. Das Problem wurde dem Log4j-Projekt aber erst etwa eine Woche vor Veröffentlichung der ersten korrigierten Version und der Problembeschreibung gemeldet. Das Projekt hat also sehr zügig reagiert, aber insgesamt war das Problem schon einige Tage früher in Hackerkreisen bekannt.
Kann ich erkennen, ob ich schon angegriffen wurde?
Das ist leider nicht robust möglich. Hinweise können zwar Zeichenketten wie etwa „jndi:“ in Log-Dateien sein. Aus dem Fehlen dieser lässt sich aber nicht schließen, dass es keinen Angriff gab.
Ist mein System jetzt korrumpiert?
Eine Remote Code Execution lässt natürlich auch eine Korruption des betroffenen Systems bis hin zum Einbau von Hintertüren zu. Der Code des Angreifers läuft zwar „nur“ unter dem Benutzer, unter dem der Java-Prozess der betroffenen Anwendung ausgeführt wurde, kann jedoch durch Kombination mit ggf. anderen vorhandenen Sicherheitslücken möglicherweise auch zu erweiterten Privilegien des Angreifers führen.
Eine Korruption eines Systems lässt sich also leider nicht ausschließen. Sofern dafür vorher Vorkehrungen getroffen wurden, kann eine Korruption durch Abgleich mit vorhandenen Fingerprints oder Einspielung älterer Sicherungen ausgeschlossen werden.
Mein System kann keine Aufrufe ins Internet machen – ist es sicher?
Nein.
Viele bekannten Angriffsszenarien nutzen zwar initial einen Aufruf zu einem Netzwerkdienst, der eine vom Angreifer kontrollierte Antwort liefert. Einen solchen Dienst zu starten ist beispielsweise mit einer Java-Klasse von wenigen Bytes Größe möglich. Der Dienst benötigt keinen privilegierten Port oder besondere Nutzer-Rechte. Auch wenn der anzugreifende Java-Prozess keine Netzkommunikation ins Internet öffnen kann, ist denkbar, dass ein Angreifer zunächst auf einem weniger gut abgesicherten internen System den notwendigen Dienst startet und diesen aufruft.
Darüber hinaus gibt es jedoch weitere Szenarien, die üblicherweise offene Kommunikationskanäle nutzen, wie etwa die Namensauflösung via DNS. Dort kann ein Information Disclosure – also die Offenlegung vertraulicher Informationen – stattfinden, etwa indem ein Passwort in der Form MYSECRET.attacker.com in einen Servernamen eingebaut wird. Schon der Versuch der Kommunikation mit diesem Server führt zunächst zu einer DNS-Anfrage der internen DNS-Server an den DNS-Server der Domain attacker.com bei der MYSECRET dorthin übertragen wird.
Es ist zu erwarten, dass weitere Szenarien auftauchen, die den externen Dienst nicht mehr voraussetzen. Die Einschränkung der Kommunikation auf Kommunikationspartner (Systeme und Ports), die für die Funktion einer Anwendung zwingend notwendig sind, ist dennoch auf jeden Fall sinnvoll. Sie alleine genügt jedoch nicht zur Absicherung gegen das aktuelle Problem.
Wie weit hilft ein Java-Patchupdate?
Aktuelle Java Patchversionen unterbinden das Nachladen von Klassen aus unsicheren Quellen. Die originalen Angriffsszenarien nutzten ein solches Nachladen, weshalb zunächst der Eindruck entstand, dass Java Patchupdates ausreichen. Dies hat sich jedoch schon nach kurzer Zeit als unzureichend herausgestellt.
Dennoch ist es wichtig regelmässige Java-Patchupdates durchzuführen. Auch in diesem Falle hat dies die Angriffsfläche verringert, die Absicherung ist aber nicht vollständig.
Behebungsmöglichkeiten
Das Apache Logging-Projekt hat am Montag, dem 13.12.2021, die neue Version 2.16.0 bereit gestellt, welches das Remote Code Execution-Problem behebt. Das verbliebe DoS- und ID-Problem wird erst mit Version 2.17.0 vom 18.12.2021 behoben. Ein Update der Log4j 2 Bibliothek auf diese Version ist die beste Behebung. Wir empfehlen deshalb dringend mit Prio 1 ein schnelles Update auf 2.17.0.
Allerdings setzt Log4j 2.17.0 minimal Java 8 voraus. Für alte Anwendungen, die noch Java 7 verwenden, hat das Projekt am 14.12.2021 Version 2.12.2 veröffentlicht, die ebenfalls nicht mehr mit Remote Code Execution angreifbar ist. Seit 22.12.2021 steht die vollständig geschützte Version 2.12.3 zur Verfügung. Diese sollte für alle Anwendungen verwendet werden, die Java 7 benötigen. Für den Einsatz mit Java 6 steht ebenfalls seit 22.12.2021 Version 2.3.1 zur Verfügung, die die gleichen Probleme beseitigt.
Sollte ein Update nicht möglich sein, empfehlen wir folgende Härtungen gegen Remote Code Execution:
- Variante 1: Patchen der Jar-Datei
Falls Sie die Log4j2-Jar-Datei log4j-core.jar oder log4j-core-[VERSION].jar in einer Anwendung eindeutig identifizieren können, empfehlen wir die Entfernung der Klasse org.apache.logging.log4j.core.lookup.JndiLookup aus dieser Datei während einer Downtime sowie einen Neustart danach. Dies kann zum Beispiel durch den Befehl
zip -q -d /pfad/zu/datei.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
geschehen. Hierbei muss der korrekte Pfad zur entsprechenden Jar-Datei angeben werden.
Einige Anwendungen haben die Jar-Datei jedoch signiert und starten nach dem Entfernen nicht mehr. In diesem Falle ist die Entfernung nicht möglich. Wir empfehlen deshalb dringend, vorher eine Sicherheitskopie der Original-Datei zu machen und nach Möglichkeit das Vorgehen auf einer Testinstanz zu prüfen, damit es nicht zu unnötigen Downtimes kommt.
Es gibt außerdem Fälle, in denen die Quelle der zu entfernenden Klasse nicht robust zu erkennen ist, etwa sogenannte Über-Jar-Dateien oder auch Repackaging. Schließlich ist auch denkbar, dass sie sowohl in einer leicht zu erkennenden Jar-Datei steckt, aber zusätzlich auch aus einer nicht aufgefallenen Quelle kommt.
Wir empfehlen deshalb die folgende Variante 2 zusätzlich und natürlich auch dort, wo Sie Variante 1 nicht durchführen können.
- Variante 2: Setzen von System Property oder Environment-Variable
Dies empfehlen wir ergänzend zu Variante 1 oder, wenn diese nicht möglich ist, als Fallback.
Setzen Sie das System Property „log4j2.formatMsgNoLookups“ oder alternativ die Environment-Variable LOG4J_FORMAT_MSG_NO_LOOKUPS auf den Wert „true„. Das Setzen als System-Property sollte auf der Kommandozeile erfolgen, indem Sie dem Java-Prozess das zusätzliche Argument „-Dlog4j2.formatMsgNoLookups=true“ mitgeben. Wenn Sie alternativ die Environment-Variable LOG4J_FORMAT_MSG_NO_LOOKUPS auf „true“ setzen, vergessen Sie bitte nicht, diese auch zu exportieren.
Bitte beachten Sie, dass der Schutz durch Variante 2 in bestimmten Fällen nicht wirkt. Der Schutz wird für viele Anwendungen vollständig sein. Es ist jedoch schwer herauszufinden, für welche Anwendungen dies nicht gilt. Ist eine Anwendung davon betroffen, dass die Schalter nicht helfen, ist sie weiter voll angreifbar. Deshalb verzichten Sie bitte nicht auf die Härtung nach Variante 1.
- Variante 3: Prüfung der Logging-Konfiguration (nur CVE-2021-45105)
Zur Behebung des verbleibenden DoS-Szenarios ohne Updates muss die Log-Konfiguration geprüft und ggf. angepasst werden. Wir verweisen hierfür auf den Eintrag zu CVE-2021-45105 auf der Seite https://logging.apache.org/log4j/2.x/security.html.
- Variante 4: Nutzung von Regeln in einer Web Application Firewall (WAF, etwa mod_security)
Ergänzend zu diesen Behebungen kann es sinnvoll sein, bei Einsatz einer Web Application Firewall (WAF), wie etwa Apache Web Server mit mod_security, gängige Angriffe durch zusätzliche Regeln abzufangen. Auch wenn diese Regeln nach einiger Zeit vom Angreifer erkannt und evtl. umgangen werden können, sichert man sich doch gegen einfache Angriffe ab und kauft sich damit Zeit für die Bestandsaufnahme betroffener Anwendung und die Umsetzung der vollständigen Behebung.
Für mod_security ist eine entsprechende Regel (Regel „1005“) beschrieben im folgenden Blog-Beitrag des wichtigen Core Rule Set (CRS) Entwicklers Christian Folini: https://coreruleset.org/20211213/crs-and-log4j-log4shell-cve-2021-44228/. Bitte beachten sie auch ggf. hinzugefügte spätere Blog-Beiträge.
Wie ist die technische Ursache für das Problem?
Die Java-Logging-Bibliothek Log4j 2 unterstützt die Auflösung von String-Referenzen der Form „${etwas}“ im Nachrichten-Teil der Log-Zeile durch Nachschlagen in Tabellen und anderen Quellen. Dies sind sogenannte Lookups. Ein solcher Quell-Typ ist ein JNDI-Lookup (Java Naming and Directory Interface), der andere Server etwa über RMI- oder LDAP-URLs ansprechen kann. Solch ein Lookup wird von Log4j 2 dann zunächst durch die Antwort dieses Servers auf den RMI- oder LDAP-Aufruf ersetzt. Da die Auflösung der Referenzen jedoch rekursiv geschieht, kann es durch weitere Auflösungen in diesen Antworten zur Ausführung von Anwendungs-Code kommen.
Andere Lookups als mittels JNDI sind bislang nicht als Angriffsvektoren bekannt. Weil sich jedoch die erste Härtung in Version 2.15.0 als unvollständig herausgestellt hat, wurden in Version 2.16.0 alle Lookup-Möglichkeiten entfernt.
Wie aber schafft es ein Angreifer einen Text der Form „${etwas}“ in eine Log-Nachricht zu bekommen, die doch meist vom Entwickler als fester Text vorgesehen wird? Nehmen wir an, eine Anwendung empfängt Daten aus dem Internet und erwartet an einer bestimmten Stelle eine Zahl. Wird dort etwas anderes geschickt, gibt die Anwendung intern eine Fehlermeldung in die Log-datei aus. Damit besser nachvollziehbar wird, warum es zu dem Fehler kam, wird dann häufig auch der Text, der statt einer Zahl empfangen wurde mit ausgegeben. Schickt der Angreifer jetzt also einfach statt der Zahl den Text „${etwas}„, wird dieser in die Fehlernachricht für das Log integriert und verursacht das Lookup.
Wie hat kippdata für seine Apache Tomcat-Distribution reagiert?
Wir haben unsere Kunden nach Bekanntgabe des Problems zeitnah über die Auswirkungen und die möglichen Behebungen informiert. Diese Information wurde sofort aktualisiert, als wir selbst weitere Angriffsszenarien gegen die bis dahin noch als sicher geltende Version 2.15.0 gefunden haben.
Wir haben unseren Kunden dann ein robustes Werkzeug bereit gestellt, um eine Härtung nach Variante 1 durchzuführen sowie genaue Informationen gegeben, wie Variante 2 umgesetzt wird. Danach haben wir umgehend neue Versionen aller unterstützten Versionslinien von Apache Tomcat bereit gestellt, in denen wir die gebündelte Log4J-Bibliothek aktualisiert haben.
Darüber hinaus haben wir unsere Support-Kunden durch Beantwortung individueller Fragen betreut und darüber hinausgehende Beratungen auch für nicht von uns gelieferte Java-Anwendungen angeboten.