Jackson Deserialization
Jackson Deserialization
Prepared by
Robert C. Seacord – Technical Director
Abstract
The Jackson JSON processor offers an alternative to Java serialization by providing
data binding capabilities to serialize Java objects to JSON and deserialize JSON
back to Java objects. Poorly written Java code that deserializes JSON strings from
untrusted sources can be vulnerable to a range of exploits including remote com-
mand execution (RCE), denial-of-service (DoS), and other attacks. These attacks are
enabled by polymorphic type handling and deserialization to overly general super-
classes. This white paper describes the features of Jackson serialization that makes it
susceptible to exploitation, demonstrates a working exploit, and identifies effective
mitigation strategies.
Table of Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3 Vulnerabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4 Mitigations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
6 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
7 Author Bio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Java serialization was introduced in JDK 1.1 and is a Core Java feature [Ora14, GJS+ 16] that allows devel-
opers to transform a graph of Java objects into a stream of bytes for storage or transmission and then back
into a graph of Java objects. Unfortunately, the Java serialization architecture is insecure which has led to
numerous vulnerabilities including remote code execution (RCE) and denial-of-service (DoS) attacks [Sea17].
According to Oracle's Secure Coding Guidelines for Java SE [Ora17]:
Java Serialization provides an interface to classes that sidesteps the field access control mech-
anisms of the Java language. As a result, care must be taken when performing serialization
and deserialization. Furthermore, deserialization of untrusted data should be avoided whenever
possible, and should be performed carefully when it cannot be avoided.
As a result, developers have looked for alternative, secure solutions that provide the features and benefits of
Java Serialization. One of the more popular alternatives is the Jackson JSON Processor.4 Jackson provides
a framework and data binding capabilities to serialize arbitrary Java objects to JSON and deserialize the
JSON back to Java objects.5 This is similar to Java Serialization in that Java programmers can serialize and
deserialize plain old Java objects (POJO) and not just Java beans.
Jackson is one of multiple Java libraries that can serialize Java object graphs into various representations
(including YAML, AMF, JSON, XML, and various binary formats) and then restore the object graphs by de-
serialization. These libraries must interact with the source or target objects during serialization and dese-
rialization to retrieve and set their properties. This interaction is most commonly based on the JavaBean's
convention of accessing object properties through getter (getXyz(), possibly isXyz() for Boolean values)
1
https://cwe.mitre.org/data/definitions/502.html
2
https://www.owasp.org/index.php/Deserialization_of_untrusted_data
3
https://www.owasp.org/index.php/PHP_Object_Injection
4
https://github.com/FasterXML/jackson-docs
5
http://www.studytrails.com/java/json/java-jackson-introduction/
6
https://fasterxml.github.io/jackson-databind/javadoc/2.9/com/fasterxml/jackson/databind/ObjectMapper.html
The expected root object type being deserialized is frequently known as the developer will want to do
something with this object once it has been reconstructed. This can be used to recursively determine
property types by using reflection.
Jackson provides annotations that can make serialization and deserialization explicit. Annotations take prece-
dence over automatic detection. Examples of annotations that influence serialization and deserialization
include:
Single argument constructors are automatically detected if the parameter type is String, Boolean, boolean,
Integer, int, Long, or long.
MapperFeature controls many of the Jackson's automatic detection features. Refer to the documentation
to view a list of customizable features and identify which are enabled by default.8 Developers who prefer
explicit settings typically disable the auto-detection settings found in MapperFeature and seldom, if ever,
use default typing.
7
https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations
8
http://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.9.1/com/fasterxml/jackson/databind/MapperFeature.
html
In the following example, serialization of Person instances is straightforward, as the types are available and
can be introspected for their properties.
However, trying to restore these values generates an exception because PhoneNumber is an abstract type.
Abstract classes cannot be instantiated and Jackson cannot determine which subtype to use without further
information.
Polymorphic type handling is also required to correctly deserialize the following class hierarchy:
Serialization of these objects must include sufficient type information to allow deserialization to instantiate
the correct subtypes. In this example, deserialization can only statically determine that Zoo contains an
Animal. During serialization, additional type information must be included for deserialization to determine
if an Animal is a Cat or Dog instance.
The enableDefaultTyping method instructs ObjectMapper to include the Java class names for all non-
final classes using the default inclusion mechanism of an additional wrapper array in JSON. The Ob-
jectMapper.DefaultTyping enum can be used to limit the classes to which default typing is applied:
• JAVA_LANG_OBJECT: properties that have Object as the declared type (including generic types without
an explicit type).
• OBJECT_AND_NON_CONCRETE: properties with the declared type of Object or an abstract type (abstract
class or interface).
• NON_CONCRETE_AND_ARRAYS: all types covered by OBJECT_AND_NON_CONCRETE and arrays of these ele-
ment types.
• NON_FINAL: all non-final types except for String, Boolean, Integer, and Double which can be correctly
inferred from JSON; as well as for all arrays of non-final types.
Default typing is a security risk if used with untrusted content. A custom TypeResolverBuilder implemen-
tation can be used to limit possible types to instantiate:
setDefaultTyping(
com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder <?>)
);
Type information can also be provided using Jackson polymorphic type handling annotations:
• @JsonTypeInfo indicates details of what type information is included in serialization. This annotation can
be used both for types (classes) and properties.
• @JsonSubTypes indicates sub-types of annotated type
• @JsonTypeName defines logical type name to use for annotated class
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
)}
@JsonTypeName("dog")
public static class Dog extends Animal {
public double barkVolume;
}
@JsonTypeName("cat")
public static class Cat extends Animal {
boolean likesCream;
public int lives;
}
}
These annotations allow the subclasses to be properly reconstructed. The JsonTypeInfo.Id specifies if
the type identifier is the fully-qualified Java class name, the Java class name with minimal path, the logical
name, uses a custom mechanism, or that no explicit type metadata is included and typing is purely done
using contextual information, possibly augmented with other annotations. The @JsonTypeInfo for the
Animal class specifies use of the logical name. The JsonTypeInfo.As enumeration specifies the inclusion
mechanism. Several inclusion mechanisms are possible including as a single, configurable property or a
wrapper array or wrapper object. Calling the enableDefaultTyping method is equivalent to the following
annotation:
One issue with this use of Jackson annotations is that it breaks encapsulation by having dependencies from
the supertype to any possible subtype. This would make it difficult to use this mechanism, for example,
when subclassing a class from a third party library. There is no way to address this problem with Jackson
annotations, but it is also possible to register a specified class as a subtype using the registerSubtypes
method in ObjectMapper or implementing a custom TypeResolverBuilder.
The ability to indicate all types is a core requirement for flexible deserialization. A significant portion of real
usage defines java.lang.Object—allowing any class which can be resolved to be deserialized.
Security researchers have identified a wide-variety of existing classes that can be used to violate the security
policies of a vulnerable Java program. These classes are often referred to as gadgets because they are
similar to gadgets in return-oriented programming [Sha07]. Gadgets consist of existing, executable code
present in the vulnerable process that can be maliciously repurposed by an attacker. In the case of Jackson
deserialization vulnerabilities, these classes contain code that is executed when an object is deserialized.
The following is a partial list of known gadgets taken from the black list for Jackson deserialization 9 :
• org.apache.commons.collections.functors.InvokerTransformer
• org.apache.commons.collections.functors.InstantiateTransformer
• org.apache.commons.collections4.functors.InvokerTransformer
• org.apache.commons.collections4.functors.InstantiateTransformer
• org.codehaus.groovy.runtime.ConvertedClosure
• org.codehaus.groovy.runtime.MethodClosure
• org.springframework.beans.factory.ObjectFactory
• com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
The Xalan-Java Compiling processor, XSLTC, can be used to compile the following source code into byte-
codes for a translet object within the TemplatesImpl instance:
["org.apache.xalan.xsltc.trax.TemplatesImpl",
{
"transletBytecodes":["…yv66vg"],
"transletName":"foo",
"outputProperties":{}
}
]
Note that the bytecodes and not the actual class definitions are stored when serializing a TemplatesImpl
object.
The transletBytecodes are executed when the getOutputProperties method is called by reflection
during deserialization to read the outputProperties property as can be seen in the following stack trace:
9
https://github.com/FasterXML/jackson-databind/commit/fd8dec2c7fab8b4b4bd60502a0f1d63ec23c24da
10
https://github.com/rcseacord/JavaSCR/tree/master/JavaSCR/src/jackson
This exploit is interesting in that it makes use of Java code already present in the JVM (Xalan) and injected
code (the exec call). The exploit is also interesting in that it utilizes a getter and not a setter method.
The deserialization vulnerability exploited in this example occurs in jackson-databind versions before 2.6.7.1,
2.7.9.1 and 2.8.9 and is described by CVE-2017-7525 11 and tracked as “Jackson Deserializer security vulner-
ability via default typing (CVE-2017-7525) #1599".12 The sample exploit was tested with Jackson-databind-
2.7.3. The exploit was successfully executed against both:
11
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7525
12
https://github.com/FasterXML/jackson-databind/issues/1599
Jackson has added a blacklist of known gadget types to mitigate the risk from exploits using these gad-
gets 13, .14 Blacklists are not a particularly effective solution and can be best thought of as a stopgap measure.
The blacklist is only effective if the set of all dangerous gadgets can be enumerated. This is clearly not the
case as can be seen in the following table of CVE details 15 :
The last entry in the table for CVE-2017-7525 describes the original vulnerability while later CVEs are the
result of gadget types that were omitted, and consequently bypass, the blacklist mechanism. Furthermore,
it would be foolish to think that the current blacklist is complete as gadgets discovered by attackers are
seldom reported.
13
https://github.com/FasterXML/jackson-databind/issues/1599
14
https://github.com/FasterXML/jackson-databind/commit/fd8dec2c7fab8b4b4bd60502a0f1d63ec23c24da
15
https://www.cvedetails.com/vulnerability-list/vendor_id-15866/product_id-42991/Fasterxml-Jackson-databind.html
The second issue is overly permissive deserialization types. Unfortunately, it is common practice to allow
any objects to be deserialized, as in the following example:
Interface types such as java.util.Serializable are also dangerous because these types are commonly
implemented by classes that may be used as gadgets.
Instead of specifying Object.class, the developer should specify the specific type of the expected root
object. These objects must be carefully written to ensure that they cannot be used as a gadget in an exploit.
Jackson allows various features of deserialization to be customized, including a number of features to en-
able/disable failure modes. Enabling all failure modes will provide additional input validation and should
help improve security. In particularly, do not disable the FAIL_ON_UNKNOWN_PROPERTIES feature (which is
enabled by default):
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES , false);
Most serialization libraries are susceptible to remote command execution and other exploits when deseri-
alizing untrusted serialized data. Jackson does not perform typing by default (including collection generic
types) and does not allow the specification of arbitrary types. Unfortunately, default typing is necessary to
correctly deserialize Java subclasses and it is common practice to for developers to specify java.lang.Ob-
ject.class to allow any object to be serialized and deserialized. The combination of polymorphic type han-
dling and deserialization to overly general superclasses allows attackers to provide specially-crafted JSON
which can be used in a wide-variety of attacks including, but not limited to, remote command execution.
Robert is the author of six books, including The CERT C Coding Standard,
Second Edition (Addison-Wesley, 2014), Secure Coding in C and C++,
Second Edition (Addison-Wesley, 2013), The CERT Oracle Secure Coding
Standard for Java (Addison-Wesley, 2012) [LMS+ 11], and Java Coding
Guidelines: 75 Recommendations for Reliable and Secure Programs
(Addison-Wesley, 2014) [LMS+ 13]. Robert is on the Advisory Board for
the Linux Foundation and an expert on the ISO/IEC JTC1/SC22/WG14
international standardization working group for the C programming
language.
[GJS+ 16] James Gosling, Bill Joy, Guy Steele, Gilad Bracha, and Alex Buckley. Java language specification:
Java se 8 edition. https://docs.oracle.com/javase/specs/jls/se8/jls8.pdf, 2016. 3
[LMS+ 11] Fred Long, Dhruv Mohindra, Robert C Seacord, Dean F Sutherland, and David Svoboda. The
CERT Oracle Secure Coding Standard for Java. Addison-Wesley Professional, 2011. 14
[LMS+ 13] Fred Long, Dhruv Mohindra, Robert C Seacord, Dean F Sutherland, and David Svoboda. Java
coding guidelines: 75 recommendations for reliable and secure programs. Addison-Wesley,
2013. 14
[MM17] Alvaro Muñoz and Oleksandr Mirosh. Friday the 13th: Json attacks. https://www.blackhat.com/
docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, July 2017. 4
[Ora17] Oracle. Secure coding guidelines for java se, version 6.0 updated for java se 9. http://www.oracle.
com/technetwork/java/seccodeguide-139067.html, September 28, 2017. 3
[Par17] Eugen Paraschiv. Jackson - decide what fields get serialized/deserialized. http://www.baeldung.
com/jackson-field-serializable-deserializable-or-not, July 20, 2017. 4
[Sal17] Tatu Saloranta. On jackson cves: Don't panic—here is what you need to know. https://medium.
com/@cowtowncoder/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6
e8062, December 22, 2017. 5
[Sea17] Robert Seacord. Combating java deserialization vulnerabilities with look-ahead object input
streams (laois). https://www.nccgroup.trust/us/our-research/combating-java-deserialization-
vulnerabilities-with-look-ahead-object-input-streams-laois/, 2017. 3
[Sha07] Hovav Shacham. The geometry of innocent flesh on the bone: Return-into-libc without function
calls (on the x86). In Proceedings of the 14th ACM conference on Computer and communications
security, pages 552–561. ACM, 2007. 8
[SS75] Jerome H Saltzer and Michael D Schroeder. The protection of information in computer systems.
Proceedings of the IEEE, 63(9):1278–1308, 1975. 11