Information Security 13 min read

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.

JD Tech
JD Tech
JD Tech
Analysis of a PriorityQueue-Based Java Deserialization Gadget Using ysoserial

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.

javadeserializationinformation securityexploitGadgetPriorityQueueysoserial
JD Tech
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.