Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Object serialization allows saving Once an object 's state as a sequence of bytes and its reconstitution at a later time. The primary application of serialization is in Java Remote Method Invocation (RMI) wherein objects must be packed (marshalled), exchanged between distributed virtual machines, and unpacked (unmarshalled). It also finds extensive use in Java Beans.After a serializable class is exported, attempts to refactor its code can become burdensome. Specifically, the old serialized form (encoded representation) must be continually supported as it is part of the published APIa particular class has been serialized, future refactoring of the class's code often becomes problematic. Specifically, existing serialized forms (encoded representations) become part of the object's published API and must be supported for an indefinite period. This can be troublesome from a security perspective, as it ; not only promotes does it promote dead code but , it also burdens forces the provider who has to eternally maintain the existing codebase. a compatible codebase for the lifetime of their products.

Classes that implement Serializable without overriding its functionality are When a class implements Serializable and does not override its functionality, it is said to be using the default serialized form. If In the event the class changes in the future, any byte stream streams produced by users of old versions of the old class will not be compatible class become incompatible with the new implementation. Moving to a custom serialized form releases the implementer from the trap of having to maintain the original serialized form as well as the corresponding version of the classConsequently, serializable classes that rely on the default serialized form cannot be evolved without compromising compatibility.

To enable compatible evolution of a serializable class, developers must use a custom serialized form, which is more flexible than a default form. Specifically,

  • Use of a custom form severs the dependence of the stream format on the code of the implementing class.
  • The code generated for deserializing a custom form can handle compatible deviations from the serialized form, like extra fields.

As a result, developers need neither maintain the earlier version of the code nor explicitly support the original serialized form.

Note that compliance with this rule, while necessary, is not sufficient to guarantee compatible evolution of serializable classes. For a full discussion of compatible evolution of serializable classes, see the Java Object Serialization Specification (version 6), Chapter 5, "Versioning of Serializable Objects" [Sun 2006].

Noncompliant Code Example

This noncompliant code example implements a GameWeapon class with a serializable field called noOfWeapons, numOfWeapons and uses the default serialization serialized form. Any changes to the internal representation of the class can break the existing serialized form.

Code Block
bgColor#FFcccc
class GameWeapon implements Serializable {
  int numOfWeapons = 10;
	    
  public String toString() {
    return String.valueOf(numOfWeapons);
  }
}

Because this class does not provide a serialVersionUID, the Java Virtual Machine (JVM) assigns it one using implementation-defined methods. If the class definition changes, the serialVersionUID is also likely to change. Consequently, the JVM will refuse to associate the serialized form of an object with the class definition when the version IDs are different.

Compliant Solution (serialVersionUID)

In this solution, the class has an explicit serialVersionUID that contains a number unique to this version of the class. The JVM will make a good-faith effort to deserialize any serialized object with the same class name and version ID.

Code Block
bgColor#ccccff
class GameWeapon implements Serializable {
  private static final long serialVersionUID = 24L;

  int noOfWeaponsnumOfWeapons = 10;
	    
  public String toString() {
    return String.valueOf(noOfWeaponsnumOfWeapons);
  }
}

Compliant Solution (serialPersistentFields)

Ideally, implement Serializable only when the class is not expected to evolve frequently should be implemented only for stable classes. One way to maintain the original serialized form , at the same time allowing the and allow the class to evolve is to use custom serialization with the help of serialPersistentFields. The static and transient fields allow one to specify what qualifiers specify which fields should not be serialized, whereas the serialPersistentFields field specifies what which fields should be serialized. It also relieves the class from defining the serializable field within the class implementation, decoupling the current implementation from the overall logic. New fields can easily be added without breaking compatibility across releases.

Code Block
bgColor#ccccff

class WeaponStore implements Serializable {
  int noOfWeaponsnumOfWeapons = 10; // Total number of weapons	
}

public class GameWeapon implements Serializable {
  WeaponStore ws = new WeaponStore();
  private static final ObjectStreamField[] serialPersistentFields
      = {new ObjectStreamField("ws", WeaponStore.class)};

  private void readObject(ObjectInputStream ois)
  throws IOException {
  throws IOException, tryClassNotFoundException {
      ObjectInputStream.GetField gf = ois.readFields();
      this.ws = (WeaponStore) gf.get("ws", ws);
    } catch (ClassNotFoundException e) { /* Forward to handler */ }
  }
	 
  private void writeObject(ObjectOutputStream oos) throws IOException {
    ObjectOutputStream.PutField pf = oos.putFields();
    pf.put("ws", ws);
    oos.writeFields();
  }
	 
  public String toString() {
    return String.valueOf(ws);
  }
}

...

Inner classes can only contain final static fields that are initialized to constants or expressions built up from constants. Consequently, it is not possible to set serialPersistentFields for an inner class (though it is possible to set it for static member classes).

Finally, serialization is easy to get wrong and must consequently be carefully designed.

Risk Assessment

Failure to provide a consistent serialization mechanism across releases can limit the extensibility of classes. If classes are extended, it is possible for compatibility issues to get introducedmay result.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SER00-J

low

Low

probable

Probable

high

High

P2

L3

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[API 06|AA. Java References#API 06]\]
\[[Sun 06|AA. Java References#Sun 06]\] "Serialization specification", "1.5  Defining Serializable Fields for a Class" and "1.7  Accessing Serializable Fields of a Class"
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 74: "Implement serialization judiciously"
\[[Harold 06|AA. Java References#Harold 06]\] 13.7.5. serialPersistentFields
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 589|http://cwe.mitre.org/data/definitions/589.html] "Call to Non-ubiquitous API"

Automated detection of classes that use the default serialized form is straightforward.

ToolVersionCheckerDescription
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

JAVA.CLASS.SER.UIDM

Missing Serial Version Field (Java)

Parasoft Jtest

Include Page
Parasoft_V
Parasoft_V

CERT.SER00.DUIDCreate a 'serialVersionUID' for all 'Serializable' classes
SonarQube
Include Page
SonarQube_V
SonarQube_V
S2057"Serializable" classes should have a "serialVersionUID"


Related Guidelines

MITRE CWE

CWE-589, Call to Non-ubiquitous API

Bibliography

[API 2014]


[Bloch 2008]

Item 74, "Implement Serialization Judiciously"

[Harold 2006]

Section 13.7.5, "serialPersistentFields"

[Sun 2006]

Java Object Serialization Specification


...

Image Added Image Added Image Added14. Serialization (SER)      14. Serialization (SER)      SER01-J. Limit the accessibility of readObject and writeObject methods