diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java index 217ffd9c62..b462c0c74d 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java @@ -12,6 +12,7 @@ import com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; +import com.fasterxml.jackson.databind.jsontype.impl.SubTypeValidator; import com.fasterxml.jackson.databind.util.ArrayBuilders; import com.fasterxml.jackson.databind.util.ClassUtil; import com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition; @@ -40,44 +41,6 @@ public class BeanDeserializerFactory private final static Class[] NO_VIEWS = new Class[0]; - /** - * Set of well-known "nasty classes", deserialization of which is considered dangerous - * and should (and is) prevented by default. - */ - protected final static Set DEFAULT_NO_DESER_CLASS_NAMES; - static { - Set s = new HashSet(); - // Courtesy of [https://github.com/kantega/notsoserial]: - // (and wrt [databind#1599]) - s.add("org.apache.commons.collections.functors.InvokerTransformer"); - s.add("org.apache.commons.collections.functors.InstantiateTransformer"); - s.add("org.apache.commons.collections4.functors.InvokerTransformer"); - s.add("org.apache.commons.collections4.functors.InstantiateTransformer"); - s.add("org.codehaus.groovy.runtime.ConvertedClosure"); - s.add("org.codehaus.groovy.runtime.MethodClosure"); - s.add("org.springframework.beans.factory.ObjectFactory"); - s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); - s.add("org.apache.xalan.xsltc.trax.TemplatesImpl"); - // [databind#1680]: may or may not be problem, take no chance - s.add("com.sun.rowset.JdbcRowSetImpl"); - // [databind#1737]; JDK provided - s.add("java.util.logging.FileHandler"); - s.add("java.rmi.server.UnicastRemoteObject"); - // [databind#1737]; 3rd party - s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); - s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean"); - s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); - s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"); - // [databind#1855]: more 3rd party - s.add("org.apache.tomcat.dbcp.dbcp2.BasicDataSource"); - s.add("com.sun.org.apache.bcel.internal.util.ClassLoader"); - DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s); - } - - /** - * Set of class names of types that are never to be deserialized. - */ - protected Set _cfgIllegalClassNames = DEFAULT_NO_DESER_CLASS_NAMES; /* /********************************************************** @@ -179,7 +142,7 @@ public JsonDeserializer createBeanDeserializer(DeserializationContext ct return null; } // For checks like [databind#1599] - checkIllegalTypes(ctxt, type, beanDesc); + _validateSubType(ctxt, type, beanDesc); // Use generic bean introspection to build deserializer return buildBeanDeserializer(ctxt, type, beanDesc); } @@ -877,19 +840,12 @@ protected boolean isIgnorableType(DeserializationConfig config, BeanDescription } /** - * @since 2.8.9 + * @since 2.8.11 */ - protected void checkIllegalTypes(DeserializationContext ctxt, JavaType type, + protected void _validateSubType(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc) throws JsonMappingException { - // There are certain nasty classes that could cause problems, mostly - // via default typing -- catch them here. - String full = type.getRawClass().getName(); - - if (_cfgIllegalClassNames.contains(full)) { - throw JsonMappingException.from(ctxt, - String.format("Illegal type (%s) to deserialize: prevented for security reasons", full)); - } + SubTypeValidator.instance().validateSubType(ctxt, type); } } diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java new file mode 100644 index 0000000000..8a273cc15a --- /dev/null +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java @@ -0,0 +1,98 @@ +package com.fasterxml.jackson.databind.jsontype.impl; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonMappingException; + +/** + * Helper class used to encapsulate rules that determine subtypes that + * are invalid to use, even with default typing, mostly due to security + * concerns. + * Used by BeanDeserializerFacotry + * + * @since 2.8.11 + */ +public class SubTypeValidator +{ + protected final static String PREFIX_STRING = "org.springframework."; + /** + * Set of well-known "nasty classes", deserialization of which is considered dangerous + * and should (and is) prevented by default. + */ + protected final static Set DEFAULT_NO_DESER_CLASS_NAMES; + static { + Set s = new HashSet(); + // Courtesy of [https://github.com/kantega/notsoserial]: + // (and wrt [databind#1599]) + s.add("org.apache.commons.collections.functors.InvokerTransformer"); + s.add("org.apache.commons.collections.functors.InstantiateTransformer"); + s.add("org.apache.commons.collections4.functors.InvokerTransformer"); + s.add("org.apache.commons.collections4.functors.InstantiateTransformer"); + s.add("org.codehaus.groovy.runtime.ConvertedClosure"); + s.add("org.codehaus.groovy.runtime.MethodClosure"); + s.add("org.springframework.beans.factory.ObjectFactory"); + s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); + s.add("org.apache.xalan.xsltc.trax.TemplatesImpl"); + // [databind#1680]: may or may not be problem, take no chance + s.add("com.sun.rowset.JdbcRowSetImpl"); + // [databind#1737]; JDK provided + s.add("java.util.logging.FileHandler"); + s.add("java.rmi.server.UnicastRemoteObject"); + // [databind#1737]; 3rd party +//s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); // deprecated by [databind#1855] + s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean"); + s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); + s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"); + // [databind#1855]: more 3rd party + s.add("org.apache.tomcat.dbcp.dbcp2.BasicDataSource"); + s.add("com.sun.org.apache.bcel.internal.util.ClassLoader"); + DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s); + } + + /** + * Set of class names of types that are never to be deserialized. + */ + protected Set _cfgIllegalClassNames = DEFAULT_NO_DESER_CLASS_NAMES; + + private final static SubTypeValidator instance = new SubTypeValidator(); + + protected SubTypeValidator() { } + + public static SubTypeValidator instance() { return instance; } + + public void validateSubType(DeserializationContext ctxt, JavaType type) throws JsonMappingException + { + // There are certain nasty classes that could cause problems, mostly + // via default typing -- catch them here. + final Class raw = type.getRawClass(); + String full = raw.getName(); + + do { + if (_cfgIllegalClassNames.contains(full)) { + break; + } + + // 18-Dec-2017, tatu: As per [databind#1855], need bit more sophisticated handling + // for some Spring framework types + if (full.startsWith(PREFIX_STRING)) { + for (Class cls = raw; cls != Object.class; cls = cls.getSuperclass()) { + String name = cls.getSimpleName(); + // looking for "AbstractBeanFactoryPointcutAdvisor" but no point to allow any is there? + if ("AbstractPointcutAdvisor".equals(name) + // ditto for "FileSystemXmlApplicationContext": block all ApplicationContexts + || "AbstractApplicationContext.equals".equals(name)) { + break; + } + } + } + return; + } while (false); + + throw JsonMappingException.from(ctxt, + String.format("Illegal type (%s) to deserialize: prevented for security reasons", full)); + } +}