The Java API [API 2006] for the Serializable
inteface declares:
Classes that require special handling during the serialization and deserialization
...
process must implement special methods with these exact signatures:
{{
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
}}Deviating from these method signatures produces a method that will, in fact, not be invoked during object serialization or deserialization. Such a method will clearly not have the expected behavior. Such methods, especially if declared
public
, might be accessible to untrusted code.Be aware that, unlike most interfaces,
Serializable
does not define these method signatures it requires. It cannot, because they areprivate
. Consequently, the Java compiler will not identify a deviant method signature.Noncompliant Code Example
This noncompliant code example shows a class
Ser
with aprivate
constructor, indicating that code external to the class should be unable to create instances of it. The class implementsjava.io.Serializable
and defines publicreadObject()
andwriteObject()
methods. Consequently, untrusted code can obtain the reconstituted objects by usingreadObject()
, and can write to the stream by usingwriteObject()
.
Code Block
bgColor #FFcccc public class Ser implements Serializable { private final long serialVersionUID = 123456789; private Ser() { // initialize } public static void writeObject(final ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); } public static void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); } }
Similarly, omitting the
static
keyword is insufficient to make this example secure; the JVM will fail to detect the two methods, resulting in failure to use the custom serialized form.Compliant Solution
This compliant solution declares the
readObject()
andwriteObject()
methodsprivate
and non-static to limit their accessibility.
Code Block
bgColor #ccccff private void writeObject(final ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); } private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); }
Reducing the accessibility also prevents malicious overriding of the two methods.
Risk Assessment
Failure to limit the accessibility of the
readObject()
andwriteObject()
methods can leave code vulnerable to untrusted invocations.
Guideline
Severity
Likelihood
Remediation Cost
Priority
Level
SER01-J
high
likely
low
P27
L1
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Bibliography
Wiki Markup [[API 2006|AA. Bibliography#API 06]\] {{Serializable}} \[[Sun 2006|AA. Bibliography#Sun 06]\] "Serialization specification" \[[Ware 2008|AA. Bibliography#Ware 08]\]
SER00-J. Maintain serialization compatibility during class evolution 16. Serialization (SER) SER02-J. Extendable classes should not declare readResolve() and writeReplace() private or static