How fastjson autoType turns JSON into RCE

How fastjson autoType turns JSON into RCE

Written by

in

The fastjson autotype feature lets a JSON document name the exact Java class it should be turned into. fastjson is a fast JSON library for Java, and autoType is the setting that reads a class name out of the payload and builds it. When the JSON comes from a user, that one feature hands the attacker a way to choose which classes your server constructs while it parses a request.

What fastjson autotype is

fastjson parses JSON into Java objects. By default it fills a target type you give it. autoType adds a special field named @type. When fastjson sees @type in the JSON, it reads the class name that follows, loads that class, and deserializes the rest of the object into it.

{
  "@type": "com.acme.billing.Invoice",
  "id": 4181,
  "total": 99.00
}

Here com.acme.billing.Invoice is not data. It is an instruction telling fastjson which class to build. If the request body is attacker controlled, the class name is attacker controlled too.

Why a class name is enough

fastjson does more than allocate the object. It calls the constructor, then setters and field assignments for the values in the JSON. So an attacker looks for a class already on the classpath whose setters do something during construction, like opening a connection to a server they control or fetching and loading code from a remote location. Point autoType at that class, fill its fields with attacker chosen values, and parsing the JSON sets the sequence in motion.

autoType turns a JSON field into a class picker. The parser stops reading data and starts building whatever the sender names.

Chained together, these reachable classes form a deserialization gadget chain that can end in remote code execution. The classes that show up in these chains are the same kind catalogued in the commons collections gadget chain. As always, no working payload is shown here. The fix is the same whichever classes exist on the box. For the ground level view of why rebuilding objects from untrusted bytes is dangerous at all, read the insecure deserialization primer.

The history in one paragraph

Older fastjson versions had autoType on and wide open. Later versions moved to a deny approach, then to autoType being off by default, and added a safeMode that refuses @type entirely. The lesson is not about one version number. Any time a parser resolves a class name from input, someone will find a class you did not expect it to reach. Blocking classes one at a time is a game you lose. Turning the feature off is the move that ends it.

How to spot fastjson autotype risk

  • Find the parse calls. Search for JSON.parseObject and JSON.parse in the codebase, then check whether the input is a request body, header, cookie, or queue message.
  • Look for autoType being enabled. Grep for ParserConfig, setAutoTypeSupport(true), and the Feature.SupportAutoType flag. Any of these means the payload can carry a class name.
  • Check the version. Very old fastjson releases are risky even without an explicit enable, because the defaults were loose. Record the exact version in use.
  • Watch for @type in traffic. Seeing that field arrive in a user supplied body is a strong signal that the parser is type aware.

How to fix fastjson autotype

  • Leave autoType off. Do not enable it on any parser that reads untrusted input. If you never call the enable methods and run a current version, the @type field is ignored.
  • Turn on safeMode. safeMode makes fastjson reject @type outright, so no class name in the JSON is ever honored. Set it globally where you can.
// Refuse @type everywhere, no class picking from input
ParserConfig.getGlobalInstance().setSafeMode(true);
  • If you must accept typed input, use a strict allowlist. Register the small set of classes you actually expect and reject every other name. An allowlist is safe because it says yes to a known list. A blocklist is not, because attackers keep finding names you forgot.
  • Deserialize into concrete types. Parse into a specific class you define with named fields, so the type is fixed by your code and the @type field has nothing to decide.
  • Keep the library patched. Upgrades both fix default behavior and remove gadget classes from the surrounding dependencies.

Why fastjson autotype is worth understanding deeply

You cannot catch this with a canned payload list, because the class that matters depends on what sits on the classpath of the target. You catch it by noticing that a parser resolves types from input, then asking whether a user can reach it and what it can build. That is the same reasoning behind jackson polymorphic deserialization in the other big Java JSON library. For the wider family of bugs where input crosses a trust boundary, see the injection and input category.

This is exactly the kind of flaw an autonomous researcher that reasons about whether untrusted input can reach a type resolving deserializer is built to find. You can read how we approach it on our about page.

Frequently asked questions

What is fastjson autoType?

autoType is the fastjson setting that reads a class name from an @type field in the JSON and builds that class. It lets a document choose its own Java type during parsing. When the JSON comes from a user, the class name is attacker controlled.

How does fastjson autoType lead to remote code execution?

fastjson runs the constructor and setters of the chosen class as it parses. An attacker points @type at a class already on the classpath whose setters do something dangerous, like opening a connection or loading code, and fills its fields. Chained together these classes form a gadget chain that can end in code execution.

Is fastjson autoType on by default?

Current versions ship with autoType off and offer a safeMode that refuses @type entirely. Older versions had it open or easy to enable. Record the exact version in use, because the defaults changed over time and very old releases are risky on their own.

How do I stop fastjson autoType attacks?

Leave autoType off on any parser that reads untrusted input, turn on safeMode so @type is rejected, and parse into concrete types you define. If you must accept typed input, register a strict allowlist of expected classes and deny all others.


Put an autonomous researcher on your own systems

UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, and a say in what it looks for. If your team ships software worth pressure testing, apply to the design partner program.