Serialization attacks are a lesser-known threat vector than the other more sensationalized threats vectors. Serialization attacks are rare, primarily due to the fact that they require more significant expertise to execute successfully. If exploited correctly, serialization vulnerabilities can lead to data breaches or other cyber-attacks.
Serialization enables objects, such as instances of particular classes, to be transformed into a serial form. In-memory data objects can be converted into binary streams while still maintaining their current state.
Deserialization refers to the reverse process. An incoming stream is read and converted into one or more data structures.
In this article, we will address the following topics
While programmers work with data objects stored in memory, there are times when the objects must be sent over the network or written to persistent storage (typically a file) to preserve some of the program’s state. Serialization allows you to store or transmit your data objects in a consistent and robust form. Then, they can be restored to their original in-memory form on another machine. Although simple data objects can be reliably represented using the same set of bytes on the same hardware architectures and compatible software, the actual byte representation of objects cannot be guaranteed for many reasons. It is not advisable to save and later reload identical byte contents, expecting to receive the same object state in general. Serialization is a way to preserve the value of software objects in a stable byte representation that can be sent over a network.
Although serialization works in a similar way across all languages and implementations, the details can vary depending on the language’s style and nuances. It is possible for class implementers to explicitly state when objects should be serializable. In this case, a standard library handles all objects. This works well, but only for objects with simple values. Complex objects may require a custom implementation to serialize, which is usually done by overriding the method in the standard library. Understanding the limitations of the standard implementation and when it can be used to serialize objects is key.
The most common security error with serialization is to trust the source of serialized data in a way that is not appropriate. Deserialization converts data to an internal representation that your programming language uses. There are few checks to see if the encoded data has been corrupted or maliciously designed. This can lead to the assumption that the standard library is doing the right thing while potentially exposing protected information. Custom code must avoid security pitfalls and express properly initialized objects to ensure that serialization works properly. Special care must be taken when objects contain or refer to other objects. This includes determining which objects should also be serialized and understanding how they work under serialization. There is often no way to verify the validity of serialized data if the source is not trustworthy.
Serialization can be a useful and secure mechanism if you have complete control over the data that you receive for deserialization. Serialization is a good idea in a few situations. One such scenario is when you need to save complex objects for later use. After you have created the serialized object, you can safely write it to a file. Your program could later read the object and deserialize them, knowing they came from a trusted source (i.e., your own program).
Another scenario is when you need to send a complicated object from one protected server into another. You control both the sender (the program responsible for serializing the object) and the receiver (the program responsible for deserializing it). You must make sure you send serialized data via an encrypted, tamper-proof channel using a secure protocol like TLS.
It is risky to attempt to deserialize data that is not serialized. This warning applies to all data that an attacker may be able to modify. Indeterminate behavior will result from the deserialization of corrupted or maliciously altered data, which is an opportunity for attackers.
Although serialized byte streams can be incompatible with different languages, their structure and form are similar at a high level. Serialized data typically begins with a header that describes what it is. This allows for easy rejection of random data. It also often includes a version number, which allows future implementation changes and maintains backward compatibility. Metadata is used to identify the class of data before the object contents can be expressed. This metadata allows the runtime at deserialization to create the correct type object. The actual field values are sent in a predetermined sequence. Complex objects will have serialization proceed recursively.
What are Serialization attacks?
Imagine an attacker sending a serialized object to an application or an API endpoint that has been compromised or contains a malicious payload. The attacker hopes that the user will execute the invalidated, untrusted input.
Serialization attacks happen when a user or victim directly deserializes any invalidated or malicious data sent by an attacker.
Another scenario is a serialization attack in which the attacker intercepts serialized objects during the transition between two servers. This happens when data is not transmitted through an encrypted, tamper-proof channel.
An attacker can gain access to the systems, networks, applications, and data by exploiting the serialization vulnerability. These attacks can lead to remote code execution and data compromise, ransomware, access control attacks (DoS attacks), server crashes, authentication bypass, SQL injects, etc.
When is an application vulnerable to these attacks?
Any application that deserializes all inputs without thorough checks and validating the source can be a target for insecure deserialization and serialization attacks.
Applications could be vulnerable even in cases where the organization controls both ends of serialization or deserialization. This could occur if data transmissions are not protected by SSL/TLS protocols that encrypt data during transit.
Lastly, applications are also vulnerable if they allow an attacker to gain access to interfaces that load serialized data. If web session information is stored in client caches using cookies, then the user can access the cookie data. An attacker could use this access to alter the access controls or gain access to the system.
How can we prevent Serialization attacks?
Serialization can be a useful tool, but it should be used with care. The implementation mechanisms can be fragile and could easily cause security issues. If an attacker is able to alter serialized data, there are many problems when deserializing false data.
Although serialized data may appear opaque at first glance, it can easily be reverse engineered to expose all information to an observer. Complex objects may have sensitive internal states that are not otherwise protected. Many serialization formats include metadata and other information, which can be more sensitive than the actual object’s values.
Avoiding serialization is the best way to avoid these potential problems. If you are unsure whether serialization is safe, it’s worth taking the time to understand the risks and consider the following mitigations.
- Write a class-specific serialization algorithm that does not expose sensitive fields and internal states to the serialization stream. It may not always be possible to remove sensitive data while still allowing the object to function properly.
- Side effects of object instantiation and deserialization (including superclasses) should be avoided.
- Never deserialize untrusted data. It is generally difficult to guarantee safety when deserializing data that has been arbitrarily altered.
- Securely store serialized data, protect it with access control or sign and encryption. A good pattern is to have the server send a signed and encrypted serialization block to a client. Later, the client can return it intact to the server. This will only be processed after signing verification.
- Sometimes, it is a good idea to clean up deserialized data within a temporary object. You can, for example, first deserialize an object by instantiating and populating its values. However, before you actually use the object, make sure that all fields are consistent and reasonable. If necessary, force an error response to destroy any objects that appear faulty.
Keep in mind that serialized information is just as valuable as any other data. If it is exposed to the public or comes from an untrusted source, it could be tampered with. It should be treated with care. You should not assume that serialized data will work in spite of being analyzed and tampered with by clever attackers.
Serialization is an effective tool that offers many benefits, but it also has inherent security risks. Although it can be very convenient, the process of serialization/deserialization can add overhead and complexity to your system that could lead to security vulnerabilities. There is no single solution, but multiple mitigations such as those outlined here can help to reduce the risk. You are more secure if you use defensive coding and mitigation.
It’s important to understand the concept of serialization and deserialization along with the potential security implications associated with these mechanisms. These attacks are not common but can be very devastating. To identify vulnerable points within your system, threat modeling is recommended. The best practices discussed in this article will help you to mitigate attack vectors.
It is important to keep an eye on the constantly changing threat landscape and prevent serialization attacks. It is not easy to maintain web application security.
Hope you liked this article on What are Serialization attacks?
Are you interested in kickstarting your career in Cybersecurity no matter your educational background or experience? Click Here to find out how.