Overview
CVE-2017-8046 describes a remote code execution risk introduced by deserializing untrusted JSON data via PATCH requests in servers using Spring Data REST versions older than 2.6.9 (Ingalls SR9) or older than 3.0.1 (Kay SR1). When combined with vulnerable Spring Boot versions older than 1.5.9 or 2.0 M6, specially crafted JSON payloads could trigger arbitrary Java code execution on the server. The underlying issue relates to Jackson deserialization and the way Spring Data REST handled PATCH updates in those old releases, which allowed an attacker to inject serialized payloads that expand into executable gadget chains. This class of vulnerability falls under CWE-20 (Improper Input Validation) and, in practice, enabled attackers to leverage object graph deserialization to execute code on the target system if the attacker could reach REST endpoints. In real Spring Boot deployments, the impact could range from remote code execution to full host compromise, dependent on the payload and the attacker’s ability to place the crafted request against exposed PATCH endpoints. The remediation is to upgrade to fixed software and apply strict input handling measures in code where PATCH semantics are implemented.
Affected Versions
Spring Data REST: prior to 2.6.9 (Ingalls SR9) and prior to 3.0.1 (Kay SR1); Spring Boot: prior to 1.5.9 and 2.0.M6
Code Fix Example
Spring Boot API Security Remediation
VULNERABLE PATTERN (illustrative, side-by-side)
// Vulnerable: PATCH handling with polymorphic typing enabled on the ObjectMapper, mirroring the risky path from CVE-2017-8046
class VulnerablePatchController {
private final ObjectMapper mapper = new ObjectMapper();
public void patch(Object payload) {
// enable polymorphic typing that can deserialize to unexpected types
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// deserializes payload into domain object, enabling potential gadget chains
DomainObject obj = mapper.convertValue(payload, DomainObject.class);
// apply and persist updates (illustrative)
}
}
// FIXED: upgrade and safer deserialization path
class SafePatchController {
private final ObjectMapper mapper = new ObjectMapper();
public void patch(Object payload) {
// disable polymorphic typing to prevent gadget-based deserialization
mapper.disableDefaultTyping();
// use a strict, whitelisted DTO for patch updates instead of deserializing into a domain model directly
UpdateDto dto = mapper.convertValue(payload, UpdateDto.class);
// apply allowed fields only and persist
}
}
// Note: In real code, DTOs would be defined with explicit fields and validation