Audit deserialization risks in Java projects, and output entry point reachability, user controllability, sinks, component/JDK/gadget conditions, exploitability, Burp requests, and payloads. A component version match can only serve as input evidence and cannot directly determine that a vulnerability exists.
Triggers and Boundaries
Trigger scenarios:
- The user requests an audit of Java deserialization vulnerabilities, deserialization RCE, gadget chains, ysoserial chains, or
DESERIALIZEsink。 - The user names
ObjectInputStream/readObject、XMLDecoder, Fastjson, XStream, JDBC deserialization, Shiro RememberMe, Log4j/JNDI. - In Pipeline stage 4,
route_tracerencountersDESERIALIZEsink, orvuln_scannermatches deserialization-related components.
Non-trigger scenarios:
- Checking only dependency versions/CVEs: use
java-vuln-scanner。 - Performing only route extraction: use
java-route-mapper。 - Only tracing call chains without determining vulnerabilities: use
java-route-tracer。 - Auditing only XML external entities: use
java-xxe-audit。 - Auditing only SQL/JDBC SQL injection: use
java-sql-audit。
XStream/XMLDecoder belong to deserialization auditing; ordinary XML external entities belong to XXE auditing.
Input Priority
If {project_name}_audit/exists, the prior outputs must be read in order:
route_mapper/: routes, HTTP methods, parameter structures, Burp request templates.route_tracer/:Sink类型 = DESERIALIZE, parameter controllability, call chains, branch conditions.vuln_report/: version risks for Fastjson, XStream, Shiro, Log4j, JDBC, CommonsCollections, etc.cross_analysis/: high-risk routes, authentication bypasses, component vulnerabilities and their association with routes.
When there is no prior output, do not force running java-route-mapper. First use commands to scan sinks, dependencies, and entry points, then perform local tracing of input sources for matched branches. For sink details see DESERIALIZATION_SINKS.md, and for component conditions see COMPONENT_PATTERNS.md。
Coverage Rules
It is not permitted to conclude "no deserialization sink" based solely on rg --type java, a small number of decompiled files, or a single keyword search. When the project contains .class、.jar, XML/Properties configuration, WebService, Struts/Spring MVC, MQ, RPC, or scheduled/import entry points, coverage must be supplemented:
- Enumerate entry points:
web.xml、applicationContext*.xml、struts*.xml, Spring MVC/REST configuration,jaxws:endpoint, Servlet/Filter/Listener, MQ listener, RPC/Dubbo/Hessian/RMI exporter, upload/import/configuration synchronization interfaces. - Scan source code and bytecode: scan
.java, decompiled directories,.classstrings, deployment configurations, and key jar contents separately; the report must state the scan scope, and "no hits in source code" must not be written as "no hits in the project". - Trace wrapper layers: when matching
XmlUtil.fromXML、JsonUtils.fromJson、SerializeUtil.deserialize、ObjectMessage.getObject、DriverManager.getConnectionand other wrapper methods, you must continue tracing to the real sink. - Trace annotation/DTO/configuration clues: after discovering clues such as
@XStreamAlias, Fastjson autoType configuration, Shiro rememberMe configuration, JMSMessageListener, JDBC dynamic datasource configuration, etc., you must examine the using classes and call chains, and must not directly judge them as "configuration only/annotation only/component only". - After matching
.class, you must decompile the matched classes, entry classes, and utility classes as needed, and then determine entry points, parameter controllability, and component/JDK/gadget conditions.
Decompilation Rules
When source code is missing, incomplete, inconsistent with the deployment package, or the preceding output only provides .class / .jar evidence, use CFR for decompilation according to DECOMPILE_STRATEGY.md .SKILL.md Do not repeatedly maintain command details; when commands need to be executed, read the shared policy.
Prioritize decompiling classes directly related to deserialization entry points, sinks, and trigger conditions:
- Controller、Action、Servlet、Filter、Listener、RPC/MQ handler。
- Classes that call
ObjectInputStream/readObject、XMLDecoder/readObject, Fastjson, XStream, Shiro RememberMe, Log4j/JNDI, JDBC URL/DataSource. - Classes that may process external data, such as configuration import, data source testing, cache reading, message consumption, task execution, and file import.
- Gadget trigger helper classes, deserialization wrapper utility classes, and component adapter classes.
Decompilation results can only serve as a source for evidence completion, and risk must still be judged in combination with entry points, controllability, call chains, component/JDK/gadget conditions, and payload verification. The report must indicate the decompilation source; when decompilation fails, record the reason for failure, and do not directly determine that a vulnerability exists based only on a class name or component hit.
Gadget Chain Audit Rules
When there are entry points that can construct objects, such as native deserialization, JMS ObjectMessage, Shiro RememberMe, XStream/Fastjson/Jackson, etc., or when dependencies hit gadget components such as CommonsCollections, CommonsBeanutils, Groovy, Spring, C3P0, Rome, Vaadin, Hibernate, Javassist, AspectJ, Xalan/TemplatesImpl, etc., chain completeness judgment must be performed according to COMPONENT_PATTERNS.md .
Gadget risk cannot be judged only by dependencies. At minimum, confirm:
- Whether the entry point can receive attacker-controlled serialized data or type declarations.
- Whether methods such as
readObject、readResolve、hashCode、compareTo、toStringare automatically triggered after deserialization. - Whether the chain can reach dangerous primitives such as reflection, command execution, JNDI, class loading, template execution, and script/expression execution.
- Whether classpath, JDK, component versions, module restrictions, class filtering, and whitelist/blacklist allow the chain to hold.
- The report must distinguish "complete chain", "missing entry point", "missing intermediate class", "missing dangerous primitive", "blocked by filter", and "component exists only".
Determination Rules
A vulnerability exists only when at least:
- A deserialization sink exists.
- The input comes from an untrusted source, or an attacker can indirectly control it.
- The entry point is reachable, and the branch conditions can be satisfied.
- Component/JDK/gadget/configuration conditions are satisfied, or can be verified in a safe manner.
- The report provides safe verification ideas, reproducible Burp requests, and payloads.
The reasons for non-exploitability must be recorded: unreachable, uncontrollable input, type whitelist, autoType disabled, unsatisfied JDK/component versions, no gadget, no outbound network conditions, only local fixed files, etc.
Output Requirements
Output to {project_name}_audit/deserialization_audit/:
{project_name}_deserialization_audit_{YYYYMMDD_HHMMSS}.md
Vulnerability ID format:{C/H/M/L}-DESER-{序号}. For the report template, see OUTPUT_TEMPLATE.md. Aggregate multi-entry vulnerabilities according to VULNERABILITY_GROUPING.md : multiple routes with the same root cause are merged into one vulnerability ID and "affected entry points" are listed; split when authentication, components, gadgets, payloads, or remediation conditions differ.
Only fully list sinks that are at risk or uncontrollable but need explanation; for safe sinks, merely mention the number and the reason they are safe in the summary. Each vulnerability must include exploitability prerequisites, a Burp request, a payload, and remediation suggestions.
Payload Rules
Outputting complete payloads is allowed, but PAYLOAD_GUIDE.md:
- must be followed. For authorized testing contexts only.
- Prefer DNS OOB,
id、whoami、calcand other low-damage verification. - Record component versions, JDK version, whether outbound network access is available, whether authentication exists, and whether gadgets exist.
- Burp requests must match the real routes, parameter names, Content-Type, and authentication state.
- Do not generate payloads for deleting files, persistence, lateral movement, or mass exploitation.
Gotchas
- Do not directly treat a component CVE match as an exploitable vulnerability.
- Do not directly judge gadget dependencies such as CommonsCollections/Beanutils as RCE; there must also be a controllable entry point, an automatic trigger point, a dangerous primitive, and an unfiltered chain.
- Do not treat
rg --type javawith no results as "the project has no sinks"; Java Web projects often have only.class, jars, and XML configuration. - Do not search only for
ObjectInputStream, and must cover XMLDecoder, Fastjson, XStream, JDBC, Shiro, and Log4j/JNDI. - Do not ignore wrapper utility classes and second-order call chains, for example
XmlUtil.fromXML、JsonUtils.fromJson、SerializeUtil.deserialize、ObjectMessage.getObject。 - Do not directly treat annotations, DTOs, or configuration clues as security conclusions;
@XStreamAlias, JMS listener, Shiro rememberMe, and dynamic DataSource must all trace the classes that use them. - Do not treat custom dangerous methods as gadgets; when there is no automatic trigger method or container trigger point, they can only be listed as code risk clues.
- Do not ignore Filters, Servlets, Listeners, RPC/MQ, configuration imports, or data source test interfaces.
- Do not directly judge
JSON.parseObject(str, SafeClass.class)as Fastjson RCE. - Do not treat unreachable utility methods as HTTP-exploitable vulnerabilities.
- Do not ignore branch conditions, authentication conditions, component/JDK conditions, and outbound network conditions.