RSTR-DES-006 — Java ObjectInputStream.readObject
Summary
Native Java deserialization (ObjectInputStream.readObject) walks the
attacker-controlled byte stream and instantiates whatever classes it
names, invoking their readObject / readResolve hooks. The
notorious CVE-2015-7501 (Apache Commons Collections) chained a
small number of common gadgets into JVM-wide RCE; the pattern has been
re-used against countless Java apps since.
Severity
Critical.
Languages
Java, Kotlin.
What rastray flags
ObjectInputStream ois = new ObjectInputStream(input); // ← flagged
Object o = ois.readObject(); // ← flagged
val ois = ObjectInputStream(input)
val o = ois.readObject() // ← flagged
What rastray deliberately does not flag
- JSON / XML / MessagePack / protobuf deserializers.
- Reads of objects you serialized yourself from a closed channel
and validated with a serialization-filter (
ObjectInputFilter) that rejects everything outside an allow-list.
How to fix it
Switch the wire format. JSON via Jackson or Gson, protobuf, Avro — any data-only format eliminates the gadget surface.
If you cannot change the format, install a JEP-290 serialization filter that rejects every class outside an explicit allow-list:
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"com.example.dto.*;java.lang.*;!*"
);
ObjectInputFilter.Config.setSerialFilter(filter);
A correctly-scoped filter is a hard lower bound — the JVM rejects the byte stream before any gadget can run.