Securing Serialization and Deserialization
Now the discussion about serialization and deserialization is about why it should be avoided in many instances and handled with care in others.
Note: Deserialization of untrusted data is inherently dangerous and should be avoided.
The serialization provides an interface two classes that sidestep the field access control mechanisms of the Java language.
Making a class serializable effectively creates a public interface to all fields of that class.
Serialization also affectively adds a hidden public instructor to a class, which needs to be considered when trying to restrict object construction.
Once an object has been serialized the Java languages access controls can no longer be enforced and attackers can access private fields in an object by analyzing its serialized byte stream. Deserialization creates a new instance of a class without invoking any constructor on that class. Deserialization of untrusted data is dangerous and should be avoided whenever possible. If it must occur, it should be handled with great care as described in some of these guidelines.
Guideline 1:
Avoid serialization for security sensitive classes. Points:
Making a class serializable can expose all the fields of a class to a bad actor, and should be avoided.
Guideline 2:
Guard sensitive data during serialization.
Points: Approaches for handling sensitive fields in serializable classes are:
- Declare sensitive fields transient
- Define the serialPersistentFields array field appropriately.
- Implement writeObject and use ObjectOutputStream.putField selectively
- Implement writeReplace to replace the instance with a serial proxy.
- implement the Externalizable interface.
Externalizable
Guideline 3:
View Deserialization the same as object construction.
Notes:
Deserialization should be designed to behave like normal construction.
- Perform the same input validation checks in a readObject method implementation as the constructor
- Create copies of deserialized mutable objects before assigning them to internal fields in a readObject implementation
- Ensure a serializable class remains totally unusable until deserialization completes successfully.
For example, use an initialized flag.
Guideline 4:
Duplicate the SecurityManager checks enforced in a class during serialization and deserialization.
Important Points
- If a serializable class enforces a SecurityManager check in its constructors, then enforce that same check in a readObject or readObjectNoData6method implementation.
- An attacker can serialize an object to bypass a security check and access the internal state simply by reading the serialized byte stream.
Guideline 5:
Understand the security permissions given to serialization and deserialization.
Points: Serialization with full permissions allows permission checks and writeObject methods to be circumvented.
1. Data should be deserialized with the least necessary privileges.
Guideline 6:
Filter untrusted serialized data.
Points: Serialization filtering was introduced in JDK 9 to improve both security and robustness when using object serialization.