Analysis of a PriorityQueue-Based Java Deserialization Gadget Using ysoserial
This article examines how a specially crafted PriorityQueue object, generated via the ysoserial tool, can be serialized and later trigger malicious code execution during Java deserialization, detailing the construction of the gadget, the transformation chain, and the underlying JVM mechanisms that enable the exploit.
The article begins by highlighting the prevalence of Java deserialization vulnerabilities and introduces the ysoserial tool as a means to generate exploit payloads, focusing on a gadget that leverages the PriorityQueue class from the Apache Commons Collections library.
It explains the two main parts of the exploit: the creation of a malicious serialized object based on PriorityQueue and the mechanism by which the deserialization process triggers the embedded payload. The construction involves generating a TemplatesImpl instance via the createTemplatesImpl method, inserting malicious bytecode into its _bytecodes field, and configuring required fields such as _name and _tfactory .
The transformation chain is built using a ChainedTransformer that combines a ConstantTransformer (returning com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter ) and an InstantiateTransformer . This chain is set as the comparator of the PriorityQueue via a TransformingComparator . When the queue is heapified during deserialization, the comparator’s compare method invokes the transformer chain.
During the compare execution, the ConstantTransformer supplies the class object, and the InstantiateTransformer creates an instance of TrAXFilter , which in turn calls TemplatesImpl.newTransformer() . This leads to TemplatesImpl.getTransletInstance() , loading the malicious StubTransletPayload class (a subclass of AbstractTranslet ) and executing its static payload via newInstance() .
The article also discusses how static initializers are triggered in Java class loading, contrasting the behavior of Class.forName() (which initializes the class) with custom class loaders that only define the class without invoking <clinit> . It references the JVM specification and the steps required for class initialization.
Finally, a concise demo (shown as evil.java ) illustrates how to construct the TemplatesImpl object via reflection and invoke getTransletInstance() to achieve code execution, summarizing the full gadget call stack and reinforcing the importance of securing deserialization pathways.
JD Tech
Official JD technology sharing platform. All the cutting‑edge JD tech, innovative insights, and open‑source solutions you’re looking for, all in one place.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.