diff -ruw jackson-mapper-asl-1.9.13-sources/org/codehaus/jackson/map/TypeDeserializer.java jackson-mapper-asl-1.9.13.redhat-00006-sources/org/codehaus/jackson/map/TypeDeserializer.java --- jackson-mapper-asl-1.9.13-sources/org/codehaus/jackson/map/TypeDeserializer.java 2012-02-16 21:11:00.000000000 -0600 +++ jackson-mapper-asl-1.9.13.redhat-00006-sources/org/codehaus/jackson/map/TypeDeserializer.java 2019-07-31 08:45:28.000000000 -0500 @@ -1,6 +1,11 @@ package org.codehaus.jackson.map; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; import org.codehaus.jackson.*; import org.codehaus.jackson.annotate.JsonTypeInfo.As; @@ -23,6 +28,20 @@ */ public abstract class TypeDeserializer { + /** + * Set of allowed packages for bean deserialization. + */ + protected final static Set ALLOW_DESER_PACKAGES; + + static { + String strlist = System.getProperty("jackson.deserialization.whitelist.packages"); + Set s = new HashSet(); + if (strlist != null) { + s = new HashSet(Arrays.asList(strlist.split(","))); + } + ALLOW_DESER_PACKAGES = Collections.unmodifiableSet(s); + } + /* /********************************************************** /* Introspection @@ -113,5 +132,51 @@ public abstract Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException; + /** + *

BZ-1507389 and CVEs related to polymorphic deserialization

+ *

Check if given type is whitelisted without loading it's class to prevent possible + * exploit with {@code static} blocks.

+ * @param parser + * @param typeId + * @throws JsonMappingException + */ + protected static void checkLegalTypes(JsonParser parser, String typeId) + throws JsonMappingException { + + if (typeId == null || "".equals(typeId)) { + return; + } + + // https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2 + // decompose arrays + while (typeId.charAt(0) == '[') { + typeId = typeId.substring(1); + if (!typeId.isEmpty() && typeId.charAt(0) == 'L') { + typeId = typeId.substring(1); + } + // we don't have to skip last ';' because of startsWith() + } + if (typeId.length() == 1) { + // base type B C D F I J S Z + return; + } + + Iterator iter = ALLOW_DESER_PACKAGES.iterator(); + + boolean pass = false; + + while (iter.hasNext()) { + if (typeId.startsWith(iter.next())) { + pass = true; + break; + } + } + + if (!pass) { + throw new JsonMappingException( + String.format("Illegal type (%s) to deserialize: prevented for security reasons", typeId)); + } + } + } \ No newline at end of file diff -ruw jackson-mapper-asl-1.9.13-sources/org/codehaus/jackson/map/jsontype/impl/TypeDeserializerBase.java jackson-mapper-asl-1.9.13.redhat-00006-sources/org/codehaus/jackson/map/jsontype/impl/TypeDeserializerBase.java --- jackson-mapper-asl-1.9.13-sources/org/codehaus/jackson/map/jsontype/impl/TypeDeserializerBase.java 2012-02-16 21:10:58.000000000 -0600 +++ jackson-mapper-asl-1.9.13.redhat-00006-sources/org/codehaus/jackson/map/jsontype/impl/TypeDeserializerBase.java 2019-07-31 08:45:28.000000000 -0500 @@ -110,7 +110,26 @@ synchronized (_deserializers) { deser = _deserializers.get(typeId); if (deser == null) { - JavaType type = _idResolver.typeFromId(typeId); + // BZ-1507389 and CVEs related to polymorphic deserialization + // the check is done after discovering type name from given json (wrapper array, + // wrapper object, ...) and before an attempt to locate the class and its + // instantiation + // without polymorphic deserialization the check should not be done even with + // default (empty) whitelist + JavaType type = null; + if (_idResolver.getMechanism() == JsonTypeInfo.Id.CLASS) { + // check without mapping before idResolver attempts to load the class + checkLegalTypes(ctxt.getParser(), typeId); + // map the class after checking + type = _idResolver.typeFromId(typeId); + } else { + // map the name to class before checking + type = _idResolver.typeFromId(typeId); + if (type != null) { + checkLegalTypes(ctxt.getParser(), type.getRawClass().getName()); + } + } + if (type == null) { // As per [JACKSON-614], use the default impl if no type id available: if (_defaultImpl == null) {