Java Security   «Prev  Next»

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.

Six Guidelines for securing Serialization and Deserialization

  • 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:
    1. Declare sensitive fields transient
    2. Define the serialPersistentFields array field appropriately.
    3. Implement writeObject and use ObjectOutputStream.putField selectively
    4. Implement writeReplace to replace the instance with a serial proxy.
    5. implement the Externalizable interface.

    Externalizable
  • Guideline 3: View Deserialization the same as object construction.
    Notes: Deserialization should be designed to behave like normal construction.
    1. Perform the same input validation checks in a readObject method implementation as the constructor
    2. Create copies of deserialized mutable objects before assigning them to internal fields in a readObject implementation
    3. 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
    1. If a serializable class enforces a SecurityManager check in its constructors, then enforce that same check in a readObject or readObjectNoData6method implementation.
    2. 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.


How Serialization has evolved between Java SE 5 and Java SE 17.

The concept of serialization has evolved between Java SE 5 and Java SE 17. Here's an overview of some key changes:
Java SE 5:
  • Basic Serialization Framework: Java SE 5 had the foundational serialization mechanisms in place. Serialization was primarily handled through the Serializable interface and the readObject and writeObject methods for custom serialization control.
  • Versioning: The concept of versioning through serialVersionUID was already established, but there were fewer tools and practices for managing version compatibility between different JVMs or class versions.
  • Security: Security considerations were less focused on serialization-specific vulnerabilities.

Changes Up to Java SE 17:
  • Security Enhancements:
    • JDK 17 introduced more robust security features around serialization. For example, JEP 415 (Context-Specific Deserialization Filters) allows applications to configure context-specific deserialization filters, enhancing security by preventing deserialization of untrusted data. This is crucial for mitigating deserialization vulnerabilities, which can lead to remote code execution.
  • Serialization Filtering:
    • Since Java 9, with JEP 290, serialization filters were introduced to limit what classes are allowed to be deserialized, providing a way to block potentially malicious class loading during deserialization. This was further enhanced in Java 17 with more flexible filter configurations.
  • Warnings and Documentation:
    • The JDK 11 release included explicit warnings in the documentation about the dangers of deserializing untrusted data. While this change was made in JDK 11, it reflects an ongoing acknowledgment of serialization's security risks, which has continued to influence development practices through to Java 17.
  • Performance and Usability:
    • Over the years, there have been incremental improvements in how serialization handles different scenarios, like handling of transient fields or custom serialization methods. However, the core mechanism has remained largely consistent, with changes focusing more on security and usability rather than altering the fundamental concept.
  • Alternative Serialization Mechanisms:
    • While not a change to Java's native serialization, there's been a growing trend to use alternative serialization mechanisms like JSON or Protocol Buffers for new systems, as recommended by authors like Josh Bloch, due to the inherent risks of Java serialization.
  • Deprecation Discussions:
    • There have been discussions and proposals (like JEP 154 which was a prank but highlighted community concerns) about potentially deprecating Java serialization due to its security challenges, although no concrete action has been taken by JDK 17.

Conclusion: While the basic mechanism of serialization has not changed dramatically, the context in which it is used has evolved significantly, with a strong emphasis on security enhancements to address deserialization vulnerabilities. Java SE 17 provides tools and practices for safer handling of serialized data, reflecting lessons learned from years of dealing with serialization in production environments.
These insights are drawn from various sources including the official Java documentation, discussions on platforms like Stack Overflow, and security blogs focusing on Java's serialization changes over time.

SEMrush Software