Every serializable container class that has private mutable instance variables must defensively copy them in the readObject() method. An adversary can append extra references to the variables to generate a new byte stream. When deserialized, this byte stream allows the creation of a container instance whose internal variable references are attacker controllable. Consequently, this allows the instance of the container class to mutate and violate its guarantees.
There is no defensive copying of the mutable components or sub-objects (Date object) in this noncompliant code example. An attacker may be able to create an instance of MutableSer so that all invariants hold when validation is carried out and later, mutate the value of the date sub-object to violate the class's contract. Any code that depends on the immutability of the sub-object is vulnerable.
class MutableSer implements Serializable {
private Date date = null; // Mutable component
public MutableSer(Date d){
date = new Date(d.getTime()); // Constructor performs defensive copying
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
// Perform validation if necessary
}
}
|
This compliant solution creates a defensive copy of the mutable Date object in the readObject() method.
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
// Defensively copy the mutable component
date = new Date(date.getTime());
// Perform validation if necessary
}
|
There is no need to copy immutable sub-objects. Also, avoid using the sub-object's {{clone()}} method because it can be overridden when the sub-object's class is non-final. Moreover, it produces only a shallow copy. The sub-objects ({{date}}) themselves must be non-final so that defensive copying can occur. It is also inadvisable to use the {{writeUnshared()}} and {{readUnshared()}} methods as an alternative \[[Bloch 2008|AA. Bibliography#Bloch 08]\]. |
Failure to defensively copy mutable components during deserialization can violate the immutability contract of an object.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
SER07- J |
low |
probable |
medium |
P4 |
L3 |
TODO
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
\[[API 2006|AA. Bibliography#API 06]\] \[[Sun 2006|AA. Bibliography#Sun 06]\] "Serialization specification: A.6 Guarding Unshared Deserialized Objects" \[[Bloch 2008|AA. Bibliography#Bloch 08]\] Item 76: "Write readObject methods defensively" |
SER06-J. Do not serialize instances of inner classes 18. Serialization (SER) SER08-J. Do not use the default serialized form for implementation defined invariants