Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: wordsmithing

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.

Noncompliant Code Example

This noncompliant code example lacks defensive copying of the mutable components or sub-objects (the Date date object in this case). An attacker may be able to create an instance of MutableSer for which all invariants hold when validation is carried out that later mutates 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.

Code Block
bgColor#FFcccc
class MutableSer implements Serializable {
  private static final Date epoch = new Date(0);
  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
  }
}

Compliant Solution

This compliant solution creates a defensive copy of the mutable Date object in the readObject() method. Note the use of field-by-field input and validation of incoming fields (see guideline SER04-J. Validate deserialized objects for additional information). Additionally, note that this compliant solution is insufficient to protect sensitive data (see guideline SER03-J. Do not serialize sensitive data for additional information).

...

Wiki Markup
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]\].

Risk Assessment

Failure to defensively copy mutable components during deserialization can violate the immutability contract of an object.

Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

SER07-J

low

probable

medium

P4

L3

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]\]
\[[Bloch 2008|AA. Bibliography#Bloch 08]\] Item 76: "Write readObject methods defensively"
\[[Sun 2006|AA. Bibliography#Sun 06]\] "Serialization specification: A.6  Guarding Unshared Deserialized Objects"

...