Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port deserialization security patch from jackson 2.x #5

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,37 @@ public class BeanDeserializerFactory
*/
private final static Class<?>[] INIT_CAUSE_PARAMS = new Class<?>[] { Throwable.class };

/**
* Set of well-known "nasty classes", deserialization of which is considered dangerous
* and should (and is) prevented by default.
*
* @since 1.9.13-atlassian-2
*/
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");
DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s);
}

/**
* Set of class names of types that are never to be deserialized.
*
* @since 1.9.13-atlassian-2
*/
protected Set<String> _cfgIllegalClassNames = DEFAULT_NO_DESER_CLASS_NAMES;

/*
/**********************************************************
/* Config class implementation
Expand Down Expand Up @@ -632,6 +663,7 @@ public JsonDeserializer<Object> createBeanDeserializer(DeserializationConfig con
if (!isPotentialBeanType(type.getRawClass())) {
return null;
}
checkIllegalTypes(type);
// Use generic bean introspection to build deserializer
return buildBeanDeserializer(config, type, beanDesc, property);
}
Expand Down Expand Up @@ -1473,4 +1505,20 @@ protected boolean isIgnorableType(DeserializationConfig config, BasicBeanDescrip
}
return status;
}

/**
* @since 2.8.9
*/
protected void checkIllegalTypes(JavaType type)
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 new JsonMappingException("Illegal type (" + full + ") to deserialize: prevented for security reasons");
}
}
}
46 changes: 46 additions & 0 deletions src/test/org/codehaus/jackson/map/interop/TestIllegalTypes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.codehaus.jackson.map.interop;

import java.io.*;

import org.codehaus.jackson.map.*;

/**
* Test case(s) to guard against handling of types that are illegal to handle
* due to security constraints.
*/
public class TestIllegalTypes extends BaseMapTest
{
static class Bean1599
{
public int id;
public Object obj;
}

public void testIssue1599() throws Exception
{
final String JSON = (
"{'id': 124,\n"
+ " 'obj':[ 'com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl',\n"
+ " {\n"
+ " 'transletBytecodes' : [ 'AAIAZQ==' ],\n"
+ " 'transletName' : 'a.b',\n"
+ " 'outputProperties' : { }\n"
+ " }\n"
+ " ]\n"
+ "}").replace('\'','"');

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
try
{
mapper.readValue(JSON, Bean1599.class);
fail("Should not pass");
}
catch (JsonMappingException e)
{
verifyException(e, "Illegal type");
verifyException(e, "to deserialize");
verifyException(e, "prevented for security reasons");
}
}
}