Add abstraction `PolymorphicTypeValidator`, for limiting subtypes allowed by default typing, `@JsonTypeInfo`
See original GitHub issue(note: moved from https://github.com/FasterXML/jackson3-dev/issues/21)
So: there are many CVEs that exploit permissive nature of class-name-based polymorphic deserialization, and especially so-called “default typing”, in which polymorphic handling is applied without annotations and with base type of java.lang.Object
.
Since set of potentially dangerous class types to exploit (“gadget types”) is unbounded, relying on block-listing (which Jackson does) is not effective in long term. And although there are mechanisms one can use to limit accessibility they are cumbersome and not well documented (Spring framework has built upon this, however, kudos to their persistence and ingenuity 😃 ).
But providing for abstraction that could allow simple strategies such as allow-listing (i.e. enumerating allowed classes), or simple predicate, should not be difficult.
Now that we are planning to do one more 2.x release, 2.10, with easier configurability (via ObjectMapper.Builder
), we should consider adding an extension point, instead of waiting until 3.0 which was the original plan.
From original issue, some further thoughts:
It should be possible to take another approach: define a new small handler API, to be invoked when:
- Resolving subtype to serialize / deserialize
- Attempting to construct serializer / deserializer
This would allow many things, like:
- Preventing deserialization and/or serialization of types deemed unsafe (or undesired?)
- Changing of type on deserialization (or, for purpose of locating serializer, also serialization?) one use of which is security check.
Callback(s) could then:
- translate type as-is, for “that’s fine”
- substitute type (subtype for deserialization; supertype for serialization)
- throw exception to indicate that type is illegal to serialize/deserialize
In theory it might even be possible to perhaps allow some special handling like “always deserialize as null”; but at this point this is speculation.
As to applicability: although we should not make definition of such handler mandatory for 2.x,
Some examples of usage can be found from unit tests src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymBaseTypeTest.java
, src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymSubTypeTest.java
and ``src/test/java/com/fasterxml/jackson/databind/jsontype/vld/BasicPTVTest.java`
but here is an example:
PolymorphicTypeValidator validator = ...; // build validator
ObjectMapper saferMapper = JsonMapper.builder()
.activateDefaultTyping(validator) // note the new name of method
.build();
String json = mapper.writeValueAsString(myDefaultTypeUsingValue);
where validator could be complete custom one, or, instance of BasicPolymorphicTypeValidator
like so:
final PolymorphicTypeValidator validator = BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(MyBaseType.class)
.build();
which would then allow all subtypes of MyBaseType
, which is something user has control over (and thereby typically has no unsafe subtypes – and definitely no widely shared ones)
EDIT 20-Aug-2019: New methods in ObjectMapper
(and MapperBuilder
) use name activateDefaultTyping()
over old now-deprecated enableDefaultTyping()
(and similarly for disable/deactivate). This to make it easier to code-search for old methods without needing argument checks.
EDIT 16-Oct-2019: Further validating this approach a good overview by Sonatype security research team: https://blog.sonatype.com/jackson-databind-the-end-of-the-blacklist
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:10 (7 by maintainers)
Top GitHub Comments
@melloware yes, I feel your pain. This is why this is #1 priority for 2.10.
I am still hoping to get 2.10.0.pr1 out within couple of weeks – most likely by early-/mid-June 2019 now.
Ok. So, the name of the handler used is
PolymorphicTypeValidator
, and there is one public convenience implementation,BasicPolymorphicTypeValidator
with builder-style construction mechanism. Mechanism are allow “opt-in” (allow-match), with one exception of allowing blocking of specific base type (oftenjava.lang.Object
). For example:BasicPolymorphicTypeValidator.builder().allowIfBaseType("com.fasterxml.").build()
com.fasterxml
packageBasicPolymorphicTypeValidator.builder().allowIfSubType(MyType.class).build()
MyType
or its sub-classand so on.