News and views from members of the Java team at Oracle
Serialization Filters were added in JDK 9 (see JEP 290) and updated in JDK 17 (see JEP 415). Serialization filters give Java applications more control over how incoming data is deserialized. Let's look at why this matters and how to configure a serialization filter.
Serialization in Java has long been a source of headaches relating to several issues with how it was implemented. A few of those issues include:
Breaks Encapsulation
Behavior Governed by "Magic" Fields and Methods: readObject, writeObject, readObjectNoData, readResolve, writeReplace, etc.
And more!
Because of the implementations issues with serialization covered above, there are real risks to deserializing data, particularly untrusted data, which is covered in more detail here. A powerful tool for protecting your application against an unsecure deserialization attack is with serialization filtering.
Filtering can be configured via a pattern which can filter based on:
Maximum depth of the object graph
Maximum references of the object graph
Maximum bytes of the object graph
Maximum array size
Allow or reject by type based on class name, package name or module name
Read here for how to construct a pattern.
A pattern based filter can be set as a security property by adding the jdk.serialFilterFactory like in the example below:
jdk.serialFilterFactory=<pattern>
To the file:
$JAVA_HOME/conf/security/java.security
A pattern based filter can also be set as a JVM arg like in the example below:
-Djdk.serialFilter=<pattern>
A filter can also be configured as code as well.
A factory method is available that can be used to create a filter by taking pattern:
ObjectInputFilter.Config.createFilter(String);
The interface ObjectInputFilter can also be implemented to provide more flexibility for filtering serialized data than what is possible with a pattern based filter:
class Filter implements ObjectInputFilter {
@Override
public Status checkInput(FilterInfo filterInfo) {
...
return null;
}
}
A filter defined in code can be set at the JVM level or even at the individual stream level.
To set a fitler at the JVM wide level setSerialFilter like in the example below:
ObjectInputFilter.Config.setSerialFilter(ObjectInputFilter);
To set a filter at the individual stream level, use setObjectInputFilter on the stream instance you want to be filtered:
ObjectInputStream.setObjectInputFilter(ObjectInputFilter);
Happy Coding!