Cybreach Consulting Prendre RDV
Retour aux articles
Vulnérabilités

Désérialisation non sécurisée : exécution de code via des objets corrompus

La sérialisation est le processus qui convertit un objet en une séquence d'octets ou une représentation textuelle (JSON, XML, binaire) pour le stocker ou le transmettre. La désérialisation reconstruit l'objet à partir de cette représentation. La vulnérabilité apparaît quand l'application désérialise des données venant d'une source non fiable (un cookie, un paramètre HTTP, un message de file d'attente) sans les valider.

Désérialisation Java et gadget chains

Java est particulièrement affecté par cette classe de vulnérabilité car sa désérialisation native invoque des méthodes sur les objets pendant leur reconstruction. Les méthodes readObject(), readResolve() et les finaliseurs sont appelés automatiquement. Si le classpath contient des bibliothèques avec des "gadgets" (classes dont les méthodes enchaînées produisent des effets dangereux), un attaquant peut construire une charge sérialisée qui exécute du code arbitraire.

Les bibliothèques couramment impliquées : Apache Commons Collections, Spring Framework, Hibernate, Jackson (avec certains modules). Ysoserial est l'outil de référence qui génère des payloads exploitant ces gadget chains connues.

Désérialisation PHP et manipulation d'objets

Exemple PHP : manipulation via désérialisation

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

Le module pickle de Python est connu pour être dangereux avec des données non fiables. La documentation officielle l'indique explicitement : "Never unpickle data received from an untrusted source." Un objet pickle malveillant peut exécuter du code arbitraire lors de la désérialisation via la méthode __reduce__.

Prévention

La règle principale : ne jamais désérialiser des données venant d'une source non fiable avec des mécanismes de sérialisation natifs. Les alternatives : utiliser des formats de données simples (JSON, protobuf) qui ne peuvent pas instancier de code arbitraire, signer cryptographiquement les données sérialisées avant de les stocker et vérifier la signature avant désérialisation, utiliser des listes blanches de classes autorisées lors de la désérialisation.

Signer les données sérialisées avant stockage

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);
}

Une question après la lecture ?

Votre application désérialise des données reçues de clients ? Envoyez un message.

Ou réservez directement un cadrage de 30 minutes

Réserver un appel