SuperAPI AI Directory

java-deserialization-audit

Security & auditing

View repository

Updated 10-16 08:11

About this skill

Java Deserialization Vulnerability Audit

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 DESERIALIZE sink。
  • The user names ObjectInputStream/readObject、XMLDecoder, Fastjson, XStream, JDBC deserialization, Shiro RememberMe, Log4j/JNDI.
  • In Pipeline stage 4,route_tracer encounters DESERIALIZE sink, or vuln_scanner matches 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:

  1. route_mapper/: routes, HTTP methods, parameter structures, Burp request templates.
  2. route_tracer/:Sink类型 = DESERIALIZE, parameter controllability, call chains, branch conditions.
  3. vuln_report/: version risks for Fastjson, XStream, Shiro, Log4j, JDBC, CommonsCollections, etc.
  4. 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,.class strings, 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.getConnection and 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, JMS MessageListener, 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:

  1. Whether the entry point can receive attacker-controlled serialized data or type declarations.
  2. Whether methods such as readObject、readResolve、hashCode、compareTo、toString are automatically triggered after deserialization.
  3. Whether the chain can reach dangerous primitives such as reflection, command execution, JNDI, class loading, template execution, and script/expression execution.
  4. Whether classpath, JDK, component versions, module restrictions, class filtering, and whitelist/blacklist allow the chain to hold.
  5. 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:

  1. A deserialization sink exists.
  2. The input comes from an untrusted source, or an attacker can indirectly control it.
  3. The entry point is reachable, and the branch conditions can be satisfied.
  4. Component/JDK/gadget/configuration conditions are satisfied, or can be verified in a safe manner.
  5. 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、calc and 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 java with 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.