Java › I/O & NIO
Why has Java's built-in serialization (ObjectInputStream.readObject()) been widely criticized as a security risk, and what specific attack does deserializing untrusted data enable?
AdvancedAnswer
Java's built-in deserialization mechanism, by its very design, reconstructs arbitrary object graphs directly from byte data, including invoking constructors and potentially triggering arbitrary code execution through crafted 'gadget chains' (sequences of otherwise-innocuous method calls across classes already present on the classpath that, when triggered in a specific unintended sequence during deserialization, can be chained together to achieve arbitrary code execution) -- deserializing data from an untrusted source (like unauthenticated network input) using readObject() has historically been the root cause of numerous serious, widely-exploited real-world vulnerabilities, which is why current best practice strongly discourages using Java's native serialization for any data crossing a trust boundary, favoring safer, more restrictive alternatives like JSON (via a library configured to avoid polymorphic type deserialization vulnerabilities) or Protocol Buffers instead.
// DANGEROUS: deserializing untrusted input directly
public Object deserializeUntrusted(byte[] untrustedData) throws Exception {
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(untrustedData))) {
return in.readObject(); // could trigger a gadget-chain exploit if the byte data is maliciously crafted
}
}
// SAFER: use a restrictive JSON library with explicit type allowlisting instead of native Java serialization
// for any data originating from outside the trust boundaryReal-world example A security audit flags a service that deserializes untrusted network input using ObjectInputStream.readObject() directly as a critical vulnerability, referencing well-documented gadget-chain exploits (like the widely-publicized Apache Commons Collections deserialization vulnerability) that allowed remote code execution against similarly-configured applications, prompting a migration to JSON-based serialization with strict type validation instead.