Detecting Fastjson 1.2.83 “Gadget-Free” RCE — a WAF / RASP / SIEM Playbook
The previous article, Fastjson 1.2.83 Gadget-Free RCE Explained, focused on how to fix. This one focuses on how to see it happen — the four layers where an attack leaves traces, plus the concrete fields, rules, and hooks you can paste into your SIEM / WAF / RASP.
1. Set the mental model first
The defining feature of gadget-free research is that it does not rely on any historical chain. Payload-signature IDS / WAF rules therefore fail. You need to shift from the byte layer to the behaviour layer. This article covers four observation points:
- Gateway / WAF: request semantics — not keywords, but JSON structure
- Application logs: what Fastjson itself throws
- RASP / bytecode: in-process class loading and reflection
- Network & host: JNDI egress, suspicious child processes, unusual ports
A hit on any layer deserves an alert; a hit on all four is almost certainly a successful attack. Fighting gadget-free is about moving from point detection to chain detection.
2. Gateway / WAF: JSON-semantic rules
Legacy regex hunting for Runtime, ProcessBuilder or ldap:// almost never catches gadget-free payloads. The new approach is to parse the JSON and look at its structure:
Core rules
- Rule A: top-level
@type— if the body isapplication/jsonand the root object contains an@typekey, alert immediately. Real polymorphism should be resolved server-side. - Rule B: nested
@type—@typeat any depth: run in audit mode first (avoid breaking legitimate allow-listed endpoints); after 7 days of observation, tune the block threshold. - Rule C: suspicious values — block outright when
@typeequalscom.sun.rowset.JdbcRowSetImpl,org.apache.tomcat.dbcp.dbcp2.BasicDataSource,javax.naming.InitialContext, or containsldap:///rmi:///dns://. - Rule D: obfuscated class names — mark high-risk if the
@typevalue contains classic bypass tricks: trailing;,[Larray notation, Base64 / Unicode escapes, inner-class$. - Rule E: unusual JSON depth — nesting > 8 layers or > 200 keys per request is rare in legitimate traffic and common in deserialization payloads. Audit-alert.
ModSecurity-style pseudo rule (illustrative)
# Semantic intent only — follow your WAF engine's actual syntax
SecRule REQUEST_HEADERS:Content-Type "@contains application/json" \
"id:'900001',phase:2,pass,nolog,ctx.check_fastjson=1"
SecRule REQUEST_BODY "@rx (?i)\"@type\"\s*:" \
"id:'900002',phase:2,chain,block,\
msg:'Fastjson autoType marker detected',\
tag:'application-multi',tag:'language-java'"
SecRule TX:CTX.CHECK_FASTJSON "@eq 1"
3. Application logs: Fastjson will tell you itself
When checkAutoType blocks a payload, Fastjson 1.2.83 throws com.alibaba.fastjson.JSONException — usually containing one of these strings:
autoType is not supportautoTypeSupport is disabled(safeMode active)expect '{', but ...(parse failure with type reference)syntax error, expect Type
Turn them into SIEM rules: same source IP, ≥ 3 of these exceptions in 5 minutes → high-severity alert + auto-add to watchlist. This is the cheapest, easiest signal to ship — many customer environments already have the logs; they just aren't rule-ified.
Halocent field note: across three real customer red-team exercises, the attackers left autoType is not support in the app log within the first 30 seconds of probing — but no one was alerting on the string, so the golden-hour was missed.
4. RASP / bytecode: the decisive layer
Even if a gadget-free payload sneaks past the WAF and past checkAutoType, producing a "side effect" still forces the JVM through a small set of APIs. Hooking those APIs yields the highest signal.
Priority RASP hook points
java.lang.ClassLoader#defineClass— anydefineClasstriggered from a deserialization stack merits a high-severity alert.javax.naming.InitialContext#lookup/Context#lookup— capture the JNDI subject; alarm onldap:///rmi://prefixes.java.lang.Runtime#exec,ProcessBuilder#start— walk the servlet thread stack; if any frame iscom.alibaba.fastjson, terminate the request.ScriptEngine#eval,GroovyClassLoader#parseClass— any scripting channel.java.net.URLClassLoaderconstruction — creating a URLClassLoader from a deserialization path is almost always malicious.
Stack-trace matching — chain, not point
Emit each hook with its call stack; alert whenever the pattern matches:
ClassLoader.defineClass
<- java.lang.reflect.Method.invoke
<- com.alibaba.fastjson.serializer.ObjectDeserializer...
<- com.alibaba.fastjson.JSON.parseObject
"From JSON.parseObject straight to defineClass" is a vanishingly rare legitimate pattern. Use it as a signature — extremely low false positive, extremely high recall.
Re-usable OpenRASP recipe
- Enable the
deserializationandwebshell_file_putplugins. - Add a custom hook in
plugins/: interceptcom.alibaba.fastjson.parser.deserializer.*#deserialze; if thetypeargument is aClassAND the current request came from an internet-facing endpoint, tag the request context. - Later, any
defineClass/exec/lookuphitting a tagged request → terminate.
5. Network & host: last-mile correlation
Even if the first three layers miss, the attacker still needs to pull in a second-stage payload. So:
- DNS: pipe all Java-process DNS through internal DoH; hits on known dnslog / collaborator / interact domains (
*.dnslog.cn,*.ceye.io,*.oastify.com,*.interact.sh, etc.) → sub-second alert. - Egress: production Java services deny outbound 389 / 636 (LDAP), 1099 / 1098 (RMI), any non-allow-listed port by default.
- Child-process alerts: any JVM spawning
sh/bash/cmd/powershell/curl/wget— unless explicitly white-listed for the business — is high-severity. - File-write alerts: JVM writing
.jsp/.class/.soin/tmp,/var/tmp, or web roots → alert and preserve for forensics.
6. Cross-layer correlation: connect the story
Each layer has some false-positive rate; the value is in the correlation. Recommended SIEM rule:
alert =
WAF(fastjson_autotype) # gateway
&& APP_LOG(autoType is not support) # application
&& RASP(defineClass from fastjson stack) # runtime
&& (Egress(LDAP/RMI) OR JVM child proc) # host
Two layers → auto-ticket high-severity; three or more → auto-isolate the host / pod and enter incident response. This is Halocent's preferred SOC configuration — < 0.1% false-positive rate and > 95% coverage on major incidents.
7. Copy-paste 8-step detection checklist
- WAF: add the 5 JSON-semantic rules (top-level @type, nested @type, suspicious values, obfuscation, extreme depth).
- WAF: run in audit for 7 days before flipping to block.
- SIEM: ingest the four Fastjson exception strings (
autoType is not support,autoTypeSupport is disabled, etc.). - SIEM: same source IP, 3 hits in 5 minutes → high severity.
- RASP: add stack-match-fastjson alerts on
defineClass,InitialContext#lookup,Runtime#exec. - DNS: deny Java-process access to known dnslog / collaborator domains by default.
- Network: block outbound LDAP / RMI / non-allow-listed ports from Java processes.
- EDR: alert on JVM child processes and on writes to web roots.
With all eight in place, your organisation's visibility into Fastjson-class RCE moves from "invisible" to "cannot land without alerting". Halocent can turn this checklist into a product-specific rollout plan for your SOC / WAF / RASP.
← Back to News & Insights