| 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 <code>BeanDeserializerFacotry</code> |
| * |
| * @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<String> DEFAULT_NO_DESER_CLASS_NAMES; |
| static { |
| Set<String> s = new HashSet<String>(); |
| // 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<String> _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(); |
| |
| main_check: |
| do { |
| if (_cfgIllegalClassNames.contains(full)) { |
| break; |
| } |
| |
| // 18-Dec-2017, tatu: As per [databind#1855], need bit more sophisticated handling |
| // for some Spring framework types |
| // 05-Jan-2017, tatu: ... also, only applies to classes, not interfaces |
| if (!raw.isInterface() && full.startsWith(PREFIX_STRING)) { |
| for (Class<?> cls = raw; (cls != null) && (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(name)) { |
| break main_check; |
| } |
| } |
| } |
| return; |
| } while (false); |
| |
| throw JsonMappingException.from(ctxt, |
| String.format("Illegal type (%s) to deserialize: prevented for security reasons", full)); |
| } |
| } |