Audit: Unsafe Jackson deserialization configurations should not be usedJAVA-A1024
Using features such as @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
or ObjectMapper.enableDefaultTyping()
with Jackson can be a security risk, as such configurations are stepping stones towards a successful exploit.
Jackson is a well known serialization/deserialization library for Java that supports deserializing data based solely on type information contained within it. This mechanism can be abused through "deserialization gadgets" to execute attacks on the target system.
Avoid specifying unsafe configurations for Jackson deserialization.
Jackson has faced a number of CVEs based on its polymorphic type handling (PTH) or polymorphic deserialization as it was previously known. This feature allows the data itself to determine the type of object it will be deserialized into. While this can be convenient, it is susceptible to exploits known as "deserialization gadgets", which can lead to remote code execution attacks. Deserialization gadgets are specific classes which may allow an attacker to perform arbitrary operations or access private data during instantiation.
Bad Practice
This isssue will be raised if a class uses the @JsonTypeInfo
annotation with the use
value set to Id.CLASS
or Id.MINIMAL_CLASS
.
@JsonTypeInfo(use = Id.CLASS)
abstract class SomeClass {
// ...
}
It will also be raised if a Jackson ObjectMapper
instance has the enableDefaultTyping()
method called on it:
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
Recommended
Use @JsonTypeInfo(use = Id.NAME)
, along with @JsonTypeName
as well as JsonSubTypes
to allow polymorphic type handling.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Square.class, name = "square"),
@JsonSubTypes.Type(value = Circle.class, name = "circle")
})
class Shape {
public String name;
Shape(String name) {
this.name = name;
}
}
@JsonTypeName("square")
class Square extends Shape {
public double length;
Square() {
this(null, 0.0);
}
Square(String name, double length) {
super(name);
this.length = length;
}
}
@JsonTypeName("circle")
class Circle extends Shape {
public double radius;
Circle() {
this(null, 0.0);
}
Circle(String name, double radius) {
super(name);
this.radius = radius;
}
}
References
@cowtowncoder
- On Jackson CVEs- OWASP Top Ten (2021) - Category A08 - Software and Data Integrity Failures
- CWE-502 - Deserialization of untrusted data
- FindSecBugs - JACKSON_UNSAFE_DESERIALIZATION