(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:
This would allow many things, like:
Callback(s) could then:
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
Ok. So, it looks like one obvious injection point is
TypeIdResolver.typeFromId()ClassNameIdResolver (and MinimalClassNameIdResolver but that's a sub-class)so that would allow handling of dangerous type at an earlier point.
We could also then pass _baseType to give bit more context.
I also think that name SubTypeValidator could be reused in 2.10, as long as we move it to a new package.
Some open questions:
I have working implementation in 2.10 (and merged into master for 3.0 as well), with core abstraction of PolymorphicTypeValidator. Different validator for annotated (@JsonTypeInfo) and default typing:
JsonMapper.builder().polymorphicTypeValidator(ptv) (new in 2.10) or ObjectMapper.setPolymorphicTypeValidator(ptv)enableDefaultTyping() methods (ObjectMapper or JsonMapper.builder())I will be tweaking details a little bit still, and add standard BasicPolymorphicTypeValidator for users to configure allow-list approach.
Can't wait to get this fix in 2.10 so my company CVE alarm stops going on for every one of my builds. Sonatype IQ server reports this every time. Any estimate on a 2.10 release with this fix in it?
@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 (often java.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.
Quick note: see #2428 for small renaming -- new methods will use "activate"/"deactivate" over "enable"/"disable", so:
mapper.activateDefaultTyping(...)
// or
ObjectMapper mapper JsonMapper.builder()
.activateDefaultTyping(validator, ...)
.build();
Note to anyone watching this issue: Jackson 2.10.0 was released and is now available via Maven Central.
Just thought I'd share that I updated the wiki page on this: https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
I left the out of date part at the top. I'm not sure if the entire page is up to date as I just saw the inconsistency in using enableDefaultTyping and changed it to activateDefaultTyping.
@retrodaredevil Thank you -- one thing worth noting would be that activateDefaultTyping() was added in 2.10, so will not work with older versions. No need to mention deprecated method, as that can be seen from 2.10 javadocs.
Removed the out of date warning
Most helpful comment
@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.