Serialize vs Deserialize in Java (with examples)

serialize vs deserialize in java

At that time, when the internet was new, applications only used a few basic high-level programming, didn’t have much functionality, and user interaction was minimal. With the advent of technology, applications have become more advanced. New frameworks and development languages, having a lot of accessibility and user-interactive features, are being introduced frequently, offering more dynamic content.

Technological advancement and application development give birth to new security threats and vulnerabilities. To deal with issues arising at the code level, web application security validation is often sought independently in the form of web application penetration testing services or more in-depth reviews such as code reviews and architecture design reviews.

In this blog, we’ll be discussing an important concept, i.e. Java Serialization and Deserialization Process and what security threats it poses in the cyber security realm.

What is serialization in Java and why is it used?

Serialization in Java is a process of changing objects to streams or bytes in memory, which are used for storage or transmission to a data file. Its purpose is mainly to preserve the state of an object so you can recreate the object if required. This process has been termed serialization or Java serialization.

The byte stream created is independent of the platform. Therefore, the object serialized at a platform can be deserialized on another platform.

What are the different methods of serialization?

Serialization is Java’s technique for writing state data into a byte stream. This technology has traditionally served the Hibernate, RMI, JPMI, EJBB, and JMS systems. Although Java specifies a default way to serialize objects, Java classes can override this default behaviour. Customised serialization is helpful when attempting to serialize an object that has a few unserializable attributes. There are multiple approaches to serialize and deserialize in Java. A few of them are listed below:

Direct struct cast (binary message)

Using this method, a user can fill data in a structured format and then send the same struct binary message as a character buffer. On the receiving side, the application or the API converts that character buffer to the same structure format and uses it.

Protobuf

Protobuf is Google’s protocol for serialization & deserialization. In this approach, a user needs to define a schema file which acts as an interface for both the sender and the receiver. The schema will be used to generate the source file out of it, and this source file is used to serialize or deserialize the data. 

JSON

JSON is short for JavaScript Object Notation. It is a lightweight data-interchange format. This is another method of representing dynamic data using human-readable strings. We can add objects, arrays, and individual values in this format. JSON is defined as the TAG:VALUE method.

ASN.1

ASN.1 is short for Abstract Syntax Notation One. It is a standard interface description language. This is the globally accepted language for communication, having the same concept as protobuf. The schema needs to be defined for the interface. The user needs to generate source code from the schema file and use this source file’s code (API) to encode & decode data.

What are the advantages of Java serialization?

Marshalling

Marshalling is the process of transforming data from one format to other. It is often taken into use when sending data over a network, as different systems may have different ways of representing data, and marshalling allows the data to be converted into a type that the receiving system can understand. Marshalling can also refer to the process of preparing data for storage, such as when serializing an object to save it to a file. Serialized state of an object makes it easier to transport objects across the information system easily by converting a Java serializable object into a byte.

Persistence

To persist or save an object’s state.

Independence

The Java serialized code is JVM-independent.

Easiness

The code is fairly easy to understand, use and customise when serialized.

What is SerialVersionUID?

The SerialVersionUID is a unique identifier for a serializable class. It is used to verify that the class of a serialized object is compatible with the class of the object that is being deserialized and that both have the same attributes. When a serialized object is deserialized, the SerialVersionUID of the serialized object is compared to the SerialVersionUID of the deserializing class. If the two values do not be the same, then an InvalidClassException is thrown, indicating that the classes are not compatible and the deserialization cannot be performed.

If a serializable class doesn’t declare a serialVersionUID, a compiler-dependent default value is automatically generated and assigned to the class at run-time. However, it is recommended to ensure that each class declares its own SerialVersionUID, as the default throws Java InvalidClassExceptions.

What is meant by deserialization in Java?

The opposite of serialization is deserialization. Serialization means converting a Java object into a byte stream to preserve its state and transport it across the network and applications. Deserialization converts the byte stream back into the original object in memory.

How does Java deserialization work? How do you deserialize a serialized object in Java?

When a byte stream is deserialized back to an object, the constructor is not required. An empty object is created, and reflection is used to write the data to the fields, with the private and final fields also included. However, to deserialize a serialized object in Java, you need to have the proper definition of the original Java object.

Why do we need to serialize and deserialize?

Serialization – The process of transforming a data source to a logical bytes stream is used in the storage of the retrieved data and, Alternatively, the data can be transferred to the memory. It is primarily used for storing objects’ states so that they can be recreated when required. This process is known as deserialization.

serialize and deserialize in a Python program

Some examples of Java serialization and deserialization

To make a Java object serializable, we use the java.io.Serializable interface.

The ObjectOutputStream class is a serializable class that contains a writeObject() method for serializing a Java object.

public final void writeObject(Object obj)

       throws IOException

Example code

Source: https://mkyong.com/java/java-serialization-examples/#hello-world-java-serialization

First, we define the Person.java object:

package com.mkyong.io.object;
import java.io.Serializable;
import java.math.BigDecimal;
public class Person implements Serializable {
   private String name;
   private int age;
   private BigDecimal salary;
   // getters setters constructor
}

Next, we serialize and then deserialize the Person.java object, as below:

package com.mkyong.io.object;
import java.io.*;
import java.math.BigDecimal;
public class HelloSerialization {
   public static void main(String[] args) {
       Person person = new Person("mkyong", 40, new BigDecimal(900));
       byte[] bytes = convertObjectToBytes(person);
       Person p = (Person) convertBytesToObject(bytes);
      System.out.println(p);
   }
   // Convert object to byte[]
   public static byte[] convertObjectToBytes(Object obj) {
       ByteArrayOutputStream boas = new ByteArrayOutputStream();
       try (ObjectOutputStream ois = new ObjectOutputStream(boas)) {
           ois.writeObject(obj);
           return boas.toByteArray();
       } catch (IOException ioe) {
           ioe.printStackTrace();
       }
       throw new RuntimeException();
   }
   // Convert byte[] to object
   public static Object convertBytesToObject(byte[] bytes) {
       InputStream is = new ByteArrayInputStream(bytes);
       try (ObjectInputStream ois = new ObjectInputStream(is)) {
           return ois.readObject();
       } catch (IOException | ClassNotFoundException ioe) {
           ioe.printStackTrace();
       }
       throw new RuntimeException();
   }
}

The above code results in the following output:

serialize vs deserialize

Explaining Java deserialize vulnerabilities

A Java serialized object is a data array that contains the state information. It is used to describe objects in fields and to record information about the fields. Using an editor in hex, it’s possible to easily access and manipulate the data.

What is insecure deserialization?

Insecure deserialization is when user-controllable data is deserialized by a web application. This potentially enables an attacker to manipulate a serialized object in order to pass malicious input into the application code.

It is even possible to replace serialized objects with objects of totally different Java classes. Due to this reason, insecure deserialization is also known as an “object injection” vulnerability.

Consider the following example:

A Java application deserialises data from a file or stream of network and receives a previously serialized object “Employee” from it. Now the application is expecting an “Employee” object, but instead, it receives a “Department” object; due to an error or a deliberate malicious activity. In most cases, might happen is that an error message may occur, crashing the application and resulting in a DoS attack or other ping flood attacks triggered by the corrupted data. In some cases, a malicious or unusual object may also be able to trigger an RCE.

serialize vs deserialize

Some examples of Java insecure deserialization vulnerabilities

Jira RCE

CVE-ID: CVE-2020-36239

Severity: Critical

Date of Disclosure: 29th July 2021

Description: According to Atlassian, attackers “could execute arbitrary code of their choice in Jira through deserialization due to a missing authentication vulnerability.”

ForgeRock OpenAM Remote Code Execution

CVE-ID: CVE-2021-35464

Severity: Critical

Date of Disclosure: 23rd June 2021

Description: According to MITRE, “ForgeRock AM server before 7.0 has a Java deserialization vulnerability in the jato.pageSession parameter on multiple pages. The exploitation does not require authentication, and remote code execution can be triggered by sending a single crafted /ccversion/* request to the server. The vulnerability exists due to the usage of Sun ONE Application Framework (JATO) found in versions of Java 8 or earlier.”

FAQs

How to prevent a Java deserialization vulnerability? How should I avoid Java serialization vulnerabilities?

When you don’t use serialized data and code, it shouldn’t be an issue for you. In the case of inheriting the interface, you can also modify the readObject() method, so the interface does not require actual deserialization. If you’re using a serialized object, you might want to inspect an input stream before deserializing.

What are serialization and deserialization in JSON?

In JSON, serialization is the process of changing a data structure or object into a string of characters so that it can be stored or transmitted as a text file, while deserialization is the process of converting a JSON string back into the JavaScript object that it represents.

Why do we need to serialize and deserialize?

Serialization – The process of transforming a data source to a logical bytes stream is used in the storage of the retrieved data. Alternatively, the data can be transferred to the memory. It is primarily used for storing objects’ states so that they can be recreated when required. This process is known as deserialization.

What are serialization and deserialization in API?

Serializing means the conversion of the state of the Java objects to byte streams, and deserialization means its reverse. Serialized data files or data are stored as external source files (or APIs), so that they can be easily accessed through networked connections.

What is deserialization?

Deserialization in Java is a procedure to reconstruct an object from bytes in a series to make an object instantaneously available. It is a reverse of a serialization process whereby data structures or objects are transformed into byte series to be stored or transferred over the network.

What is the use of a serializable interface in Java?

In Java, the serializable interface is a marker interface that represents that a class can be serialized. When you have to store a copy of an object and send it to another process or application running on the same system or network, you use a serializable interface.

How do you deserialize a serialized object in Java?

For serializing objects, we invoke Write object() method for object OutputStream, and for Deserialization, we invoke Write object() method for the object InputStream.

Do we need to implement serialization in every class?

Class properties are inherited by all its sub-classes, so if a parent class implements serialization, the child class would also be serializable. However, the above scenario is not true if only the child class is serializable.

Article Contents

Sharing is caring! Use these widgets to share this post
Twitter
LinkedIn
WhatsApp
Email
Scroll to Top