Wondering why deserialization vulnerabilities are so popular?
Learn more about deserialization, why it happens, and CPU fixes.
In 2017, around 60 remote code execution (RCE) deserialization vulnerabilities were reported, not including deserialization issues that only impact the availability of a system (Denial-of-Service), according to cvedetails.com. To date, in 2018, more than 80 such vulnerabilities have been reported. In the past, WebLogic, Oracle’s Enterprise Java application server, has been extensively patched against deserialization issues. The latest October 2018 Oracle Critical Patch Update (CPU) fixes another series of deserialization issues in WebLogic.
Because of this, I am often asked why Java deserialization vulnerabilities are being discovered so frequently? Is there a fundamental design flaw somewhere?
There are several reasons why deserialization issues keep arising.
First and foremost, it is essential to understand that deserialization vulnerabilities occur due to the combination of two fundamental design flaws. To begin with, some serialization/deserialization specifications and implementations, such as the native Java serialization mechanism, were designed with no way to validate the expected object type before the deserialization process. The Java runtime system will happily deserialize (convert to an object) any serialized stream without first validating its content and/or the expected types. The other design flaw is at the application level. If the serialization mechanism or the runtime system does not validate the serialized stream, then the application must not expose deserialization end-points to unsafe inputs. The deserialization end-points must not be accessible by untrusted users. This is why the vulnerability is officially named “Deserialization of untrusted data.”
The Java Virtual Machine (JVM) has only recently offered support for a new mechanism that allows developers and security engineers to protect deserialization end-points by enforcing type filtering. However, this introduced another layer of complexity around the already confusing nature of the vulnerability.
This brings us to the second reason why deserialization issues keep arising. This unsafe process had not been (and possibly still is not) comprehensively understood by software developers who have designed their applications to expose deserialization components to potentially unsafe, user-controlled, serialized streams.
Even when the vulnerability is fully understood by the software developers, the issue might not be properly remediated. Since it is a design flaw, in many cases, it can be very costly and complex to make changes in the code, as it could even require a redesign of part of the system. This complexity sometimes forces developers to cut corners and mitigate the vulnerability using a blacklist approach, which is an easy way to block known exploits. However, even though blacklisting may help mitigate known exploits, it is prone to new attack vectors.
Third, security researchers are attracted by the challenge of bypassing security mechanisms that depend on simplistic controls such as blacklists, which in most cases are incomplete. The challenge becomes increasingly attractive if the blacklist mechanism protects a high-value target such as application servers (e.g. WebLogic).
The final reason that makes this type of vulnerability attractive to researchers is because of its high impact and severity. In most cases, deserialization vulnerabilities could allow attackers to perform remote code execution without authentication. Such an attack could take over the victim’s system and potentially even compromise the whole network.
It should be noted that the above applies to deserialization vulnerabilities that allow remote code execution. There is another type of deserialization issue that has a different impact, namely Denial-of-Service, often via unrestricted memory allocation. This type of deserialization issue generally doesn’t require a redesign of the application and, in most cases, can be fixed or mitigated by simply patching the code to properly do input validation of the expected size of memory that should be allocated. However, there are exceptions to this rule, as there are known Denial-of-Service deserialization exploits that cannot be fixed by simply patching the application code. Because of its reduced impact, this type of deserialization vulnerabilities is less popular targets for security researchers.
To be clear, deserialization vulnerabilities are primarily caused by design flaws at the serialization and application levels, and they are not code-level bugs. The best way to avoid deserialization vulnerabilities is to design applications in such a way that does not perform open-ended object deserialization of untrusted data.
Changing the serialization format to XML or JSON does not necessarily eliminate deserialization issues, as there are known deserialization vulnerabilities with these formats and libraries as well. If changing the source code is not feasible or redesigning the application is not an option and usage of blacklists and whitelists is not desired, there are RASP solutions that can protect against such issues with no code or design changes and without depending on heuristic approaches.