-
Type:
CSR
-
Resolution: Approved
-
Priority:
P3
-
Component/s: core-libs
-
None
-
behavioral
-
minimal
-
-
System or security property
-
JDK
Summary
Provide of a subset of JEP 415: Context-Specific Deserialization Filters for JDK 11. Allow applications to configure context-specific and dynamically-selected deserialization filters via a JVM-wide filter factory that is invoked to select a filter for each deserialization stream.
Problem
Deserializing untrusted data is an inherently dangerous activity because the content of the incoming data stream determines the objects that are created, the values of their fields, and the references between them. In many typical uses the bytes in the stream are received from an unknown, untrusted, or unauthenticated client. By careful construction of the stream, an adversary can cause code in arbitrary classes to be executed with malicious intent. If object construction has side effects that change state or invoke other actions, those actions can compromise the integrity of application objects, library objects, and even the Java runtime. The key to disabling deserialization attacks is to prevent instances of arbitrary classes from being deserialized, thereby preventing the direct or indirect execution of their methods.
Solution
Context-Specific Deserialization Filtering is used to select the filter for each stream when the stream is created, in the constructor or before first invocation to read objects. The filter factory can be provided by the application and is configured to apply across all threads and frameworks. The factory is designed and implemented for the specific application purpose and should take into account all deserialization execution contexts that are to be protected within the Java runtime. The filter factory is invoked in the constructor of ObjectInputStream to select and return the deserialization filter for the stream.
An application’s developer is in the best position to understand the structure and operation of the application’s components. This enhancement enables the application developer to construct and apply filters to every deserialization operation.
Specification
The scope of JEP 415: Context-Specific Deserialization Filters is reduced to include the filter factory API and behavior and configuration via command line or security properties with JDK scope. There are no new APIs, no utility functions; the behavior is a strict subset of JEP 415.
The behavior is opt-in based on the presence of the jdk.serialFilterFactory
system property on the command line or
the jdk.serialFilterFactory security property.
If set, the JVM-wide filter factory selects the filter for each stream
when the stream is constructed and when a stream-specific filter is set.
If the JVM-wide filter factory is not set, the behavior is compatible with earlier versions.
If the Java virtual machine is started with the property jdk.serialFilterFactory
system property on the command line or
the jdk.serialFilterFactory security property, its value
is the fully qualified name of the class to use as the JVM-wide deserialization filter factory.
The system property overrides the security property if both are defined.
Setting the jdk.serialFilterFactory with System.setProperty does not set the filter factory.
The class must be public, must have a public zero-argument constructor, implement the
BinaryOperator<ObjectInputFilter> interface, provide its implementation and
be accessible via the application class loader.
If the filter factory constructor is not invoked successfully, a java.lang.ExceptionInInitializerError
is thrown and subsequent use of the filter factory for deserialization fails with
java.lang.IllegalStateException.
The JVM-wide filter factory is a function invoked when each ObjectInputStream is constructed
and when the stream-specific filter is set using ObjectInputStream.setObjectInputFilter(ObjectInputFilter).
The parameters are the current filter and a requested filter and it
returns the filter to be used for the stream. When invoked from the ObjectInputStream constructors,
the first parameter is null and the second parameter is the static JVM-wide filter.
When invoked from ObjectInputStream.setObjectInputFilter,
the first parameter is the filter currently set on the stream (which was set in the constructor),
and the second parameter is the filter given to ObjectInputStream.setObjectInputFilter.
The current and new filter may each be null and the factory may return null except
if the current filter is non-null, the filter factory must return a non-null filter,
otherwise an IllegalStateException is thrown from setObjectInputFilter.
This precaution is taken to prevent unintentional disabling of filtering after it has been enabled.
The factory may throw runtime exceptions to signal incorrect use or invalid parameters.
Note that the filter factory implementation can also use any contextual information at its disposal, for example, extracted from the application thread context, or its call stack, to compose and combine a new filter. It is not restricted to only use its two parameters.
The $JAVA_HOME/conf/security/java.security configuration file includes the following:
# Deserialization system-wide filter factory
#
# A filter factory class name is used to configure the system-wide filter factory.
# The filter factory selects the java.io.ObjectInputFilter to use for each
# ObjectInputStream when invoked with a current and a requested filter.
# The class must be public, must have a public zero-argument constructor, implement the
# java.util.function.BinaryOperator<java.io.ObjectInputFilter> interface,
# provide its implementation and be accessible via the application class loader.
# See the release notes for more details.
#
# If the system property jdk.serialFilterFactory is also specified, it supersedes
# the security property value defined here.
#
#jdk.serialFilterFactory=<classname>