Cybreach Consulting Prendre RDV
Back to articles
Vulnerabilities

Insecure deserialization: code execution through corrupted objects

Serialisation is the process that converts an object into a byte sequence or text representation (JSON, XML, binary) for storage or transmission. Deserialisation reconstructs the object from this representation. The vulnerability appears when the application deserialises data from an untrusted source (a cookie, HTTP parameter, queue message) without validating it.

Java deserialization and gadget chains

Java is particularly affected by this vulnerability class because its native deserialization invokes methods on objects during reconstruction. Methods readObject(), readResolve(), and finalisers are called automatically. If the classpath contains libraries with "gadgets" (classes whose chained methods produce dangerous effects), an attacker can craft a serialised payload that executes arbitrary code.

Commonly involved libraries: Apache Commons Collections, Spring Framework, Hibernate, Jackson (with certain modules). Ysoserial is the reference tool that generates payloads exploiting these known gadget chains.

PHP deserialization and object manipulation

PHP example: manipulation through deserialization

class User {
  public $role = 'user';
  public $redirectTo = '/dashboard';
}

// Données venant d'un cookie non signé :
$user = unserialize($_COOKIE['user']);

// Attaquant modifie le cookie avec :
// O:4:"User":2:{s:4:"role";s:5:"admin";s:10:"redirectTo";s:1:"/";}
// Résultat : $user->role === 'admin'

Python pickle

Python's pickle module is known to be dangerous with untrusted data. The official documentation states this explicitly: "Never unpickle data received from an untrusted source." A malicious pickle object can execute arbitrary code during deserialization via the __reduce__ method.

Prevention

The main rule: never deserialise data from an untrusted source using native serialization mechanisms. Alternatives: use simple data formats (JSON, protobuf) that cannot instantiate arbitrary code, cryptographically sign serialised data before storing it and verify the signature before deserialization, use class whitelists during deserialization.

Sign serialised data before storage

const crypto = require('crypto');

function sign(data) {
  const payload = JSON.stringify(data);
  const sig = crypto.createHmac('sha256', process.env.SECRET_KEY)
                    .update(payload).digest('hex');
  return payload + '.' + sig;
}

function verify(signed) {
  const [payload, sig] = signed.split('.');
  const expected = crypto.createHmac('sha256', process.env.SECRET_KEY)
                         .update(payload).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    throw new Error('Signature invalide');
  }
  return JSON.parse(payload);
}

A question after reading?

Does your application deserialise data received from clients? Send a message.

Or book a 30-minute scoping call directly

Book a call