CVE-2019-17556: Unsafe deserialization in Apache Olingo

Artem Smotrakov
Dec 21, 2019 · 4 min read

Some time ago I wrote about one security issue which I found in the library. This post describes another little vulnerability in Apache Olingo. The issue has been fixed in the 4.7.0 release as well.

By the way, Apache Olingo is a Java library that implements the Open Data Protocol (OData). This protocol allows the creation and consumption of queryable and interoperable RESTful APIs in a simple way.

(Originally published at https://blog.gypsyengineer.com)

The issue

Apache Olingo has the AbstractService class which is part of the public API. According to the Javadoc, the class is an entry point for the proxy mode. It gives access to entity container instances. The constructor of the class takes compressed metadata. More precisely, the constructor expects a serialized XMLMetadata object which is encoded with Base64 and compressed with GZIP. Which serialization mechanism does it use? It's the default Java serialization which is known to be vulnerable to deserialization attacks. Here is how the constructor processes the compressed metadata:

protected AbstractService(final String compressedMetadata, final String metadataETag,
final ODataServiceVersion version, final String serviceRoot, final boolean transactional) {
ByteArrayInputStream bais = null;
GZIPInputStream gzis = null;
ObjectInputStream ois = null;
XMLMetadata metadata = null;
try {
// use commons codec's Base64 in this fashion to stay compatible with Android
bais = new ByteArrayInputStream(new Base64().decode(compressedMetadata.getBytes("UTF-8")));
gzis = new GZIPInputStream(bais);
ois = new ObjectInputStream(gzis);
metadata = (XMLMetadata) ois.readObject();

First, it uses the Base64.decode() method to decode the input data. Then, it converts the decoded data to a byte array and wraps the array into a ByteArrayInputStream instance. Next, the input stream is wrapped into a GZIPInputStream object to decompress the data. Finally, the GZIP input stream is wrapped into an ObjectInputStream to deserialize the metadata.

By default, the ObjectInputStream doesn't apply any check when it deserialized data. It means that if an attacker is able to feed malicious metadata to a class that extends the AbstractService, then in the worse case it can result in executing the attacker's code.

The severity of the issue highly depends on how a particular application uses the AbstractService class, and where the metadata comes from.

If an application loads the metadata from a protected resource, the attacker has to find a way how to write malicious metadata to the protected resource. It may be not easy. For example, if the metadata is loaded from a properly configured database, then the attacker has to find a SQL injection or another way that would allow him to inject malicious data into the database. Or, if the application loads the metadata from a file which has proper access rights, then the attacker has to find a way how he can write to the file.

On the other hand, if an application receives the metadata via the network, it may be much easier for the attacker to make the application load his malicious data.

Nevertheless, the project maintainers agreed to make the AbstractService class a bit more safe to use.

The solution

The problem has been mitigated by implementing a whitelist for classes which are allowed for deserialization. It may be done, for example, by extending the ObjectInputStream class and implementing the whitelisting in the overridden resolveClass() method. But it was not necessary because Olingo uses Apache IO which offers the ValidatingObjectInputStream class for implementing such a whitelist. Another option might be the filters that have been added in JEP 290, but this way would require using newer versions of Java.

The fix was quite simple:

  • Added a factory method createObjectInputStream() which creates a ValidatingObjectInputStream instance configured with a whitelist of classes which are allowed for deserialization.

The patch has been released in Apache Olingo 4.7.0.

Is my application vulnerable?

Definitely, not each and every application which uses older versions of Apache Olingo is vulnerable. There are at least two things which need to be checked in an application which uses Apache Olingo:

  1. Does it uses the AbstractService class?

Answers to the questions above depend on a specific application. If both answers are yes, then it’s likely that the application is vulnerable.

Conclusion

This issue is another example of a deserialization vulnerability when an application uses the default Java deserialization mechanism. Not all applications, which use Apache Olingo, are vulnerable by default. But it may be better to stay on the safe side and update the library.

References


Originally published at https://blog.gypsyengineer.com on December 21, 2019.


InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. In a nutshell, we are the largest InfoSec publication on Medium. Maintained by Hackrew

Artem Smotrakov

Written by

I write about Java and security

InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. In a nutshell, we are the largest InfoSec publication on Medium. Maintained by Hackrew

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade