LFI2RCE via Eternal waiting

Support HackTricks

Basic Information

Standaard, wanneer 'n lêer na PHP opgelaai word (selfs al verwag dit nie), sal dit 'n tydelike lêer in /tmp genereer met 'n naam soos php[a-zA-Z0-9]{6}, alhoewel ek sommige docker beelde gesien het waar die gegenereerde lêers geen syfers bevat nie.

In 'n plaaslike lêerinvoeging, as jy daarin slaag om daardie opgelaaide lêer in te sluit, sal jy RCE kry.

Let daarop dat standaard PHP slegs toelaat om 20 lêers in 'n enkele versoek op te laai (gestel in /etc/php/<version>/apache2/php.ini):

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

Ook, die aantal potensiële lêernames is 62*62*62*62*62*62 = 56800235584

Ander tegnieke

Ander tegnieke berus op die aanval van PHP protokolle (jy sal nie in staat wees as jy net die laaste deel van die pad beheer nie), die pad van die lêer openbaar, die misbruik van verwagte lêers, of maak PHP 'n segmentasiefout ly sodat opgelaaide tydelike lêers nie verwyder word nie. Hierdie tegniek is baie soortgelyk aan die laaste een, maar sonder om 'n nuldag te vind.

Ewige wag tegniek

In hierdie tegniek het ons net 'n relatiewe pad nodig om te beheer. As ons daarin slaag om lêers op te laai en die LFI nooit te laat eindig nie, sal ons "genoeg tyd" hê om brute-force opgelaaide lêers en vind enige van die opgelaaide.

Voordele van hierdie tegniek:

  • Jy moet net 'n relatiewe pad binne 'n insluiting beheer

  • Vereis nie nginx of 'n onverwagte vlak van toegang tot log lêers nie

  • Vereis nie 'n 0 dag om 'n segmentasiefout te veroorsaak nie

  • Vereis nie 'n pad openbaar nie

Die hoofprobleme van hierdie tegniek is:

  • 'n Spesifieke lêer(s) moet teenwoordig wees (daar mag meer wees)

  • Die mal hoeveelheid potensiële lêernames: 56800235584

  • As die bediener nie syfers gebruik nie is die totale potensiële hoeveelheid: 19770609664

  • Standaard kan slegs 20 lêers in 'n enkele versoek opgelaai word.

  • Die maksimum aantal parallelle werkers van die gebruikte bediener.

  • Hierdie limiet saam met die vorige kan hierdie aanval te lank laat duur

  • Tydsduur vir 'n PHP versoek. Ideaal gesproke moet dit ewige wees of die PHP-proses moet doodgemaak word sonder om die tydelike opgelaaide lêers te verwyder, anders sal dit ook 'n pyn wees

So, hoe kan jy maak dat 'n PHP insluiting nooit eindig nie? Net deur die lêer /sys/kernel/security/apparmor/revision in te sluit (nie beskikbaar in Docker houers ongelukkig...).

Probeer dit net deur te bel:

php -a # open php cli
include("/sys/kernel/security/apparmor/revision");

Apache2

Standaard ondersteun Apache 150 gelyktydige verbindings, volgens https://ubiq.co/tech-blog/increase-max-connections-apache/ is dit moontlik om hierdie getal tot 8000 te verhoog. Volg dit om PHP met daardie module te gebruik: https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04.

Standaard, (soos ek in my toetse kan sien), kan 'n PHP-proses ewig duur.

Kom ons doen 'n bietjie wiskunde:

  • Ons kan 149 verbindings gebruik om 149 * 20 = 2980 tydelike lêers met ons webshell te genereer.

  • Dan, gebruik die laaste verbinding om brute-force potensiële lêers.

  • Teen 'n spoed van 10 versoeke/s is die tye:

  • 56800235584 / 2980 / 10 / 3600 ~= 530 ure (50% kans in 265h)

  • (sonder syfers) 19770609664 / 2980 / 10 / 3600 ~= 185h (50% kans in 93h)

Let daarop dat ons in die vorige voorbeeld heeltemal ander kliënte DoSing!

As die Apache-bediener verbeter word en ons 4000 verbindings kan misbruik (halfpad na die maksimum getal). Ons kan 3999*20 = 79980 lêers skep en die getal sou verminder tot ongeveer 19.7h of 6.9h (10h, 3.5h 50% kans).

PHP-FMP

As die webblad PHP-FMP gebruik in plaas van die gewone php-mod vir apache om PHP-skripte uit te voer (dit verbeter die doeltreffendheid van die webblad, so dit is algemeen om dit te vind), is daar iets anders wat gedoen kan word om die tegniek te verbeter.

PHP-FMP laat toe om die parameter request_terminate_timeout in /etc/php/<php-version>/fpm/pool.d/www.conf te konfigureer. Hierdie parameter dui die maksimum aantal sekondes aan wanneer versoek aan PHP moet beëindig (oneindig per standaard, maar 30s as die param nie kommentaar is nie). Wanneer 'n versoek deur PHP verwerk word, word die aangeduide aantal sekondes, dit vermoor. Dit beteken dat as die versoek tydelike lêers opgelaai het, omdat die php-verwerking gestop is, daardie lêers nie verwyder gaan word nie. Daarom, as jy 'n versoek kan laat duur vir daardie tyd, kan jy duisende tydelike lêers genereer wat nie verwyder sal word nie, wat die proses om hulle te vind versnel en die waarskynlikheid van 'n DoS op die platform verminder deur al die verbindings te verbruik.

So, om DoS te vermy, kom ons veronderstel dat 'n aanvaller slegs 100 verbindings terselfdertyd sal gebruik en die maksimum verwerkingstyd van php deur php-fmp (request_terminate_timeout) is 30s. Daarom is die aantal tydelike lêers wat per sekonde gegenereer kan word 100*20/30 = 66.67.

Dan, om 10000 lêers te genereer, sal 'n aanvaller nodig hê: 10000/66.67 = 150s (om 100000 lêers te genereer, sal die tyd 25min wees).

Dan kan die aanvaller daardie 100 verbindings gebruik om 'n soek brute-force uit te voer. **** Veronderstel 'n spoed van 300 req/s, die tyd wat nodig is om dit te ontgin is die volgende:

  • 56800235584 / 10000 / 300 / 3600 ~= 5.25 ure (50% kans in 2.63h)

  • (met 100000 lêers) 56800235584 / 100000 / 300 / 3600 ~= 0.525 ure (50% kans in 0.263h)

Ja, dit is moontlik om 100000 tydelike lêers in 'n EC2 medium grootte instansie te genereer:

Let daarop dat dit voldoende sou wees om die kwesbare LFI-bladsy in te sluit om die tydsduur te aktiveer, sodat dit in 'n ewige insluitingslus ingaan.

Nginx

Dit lyk of Nginx standaard 512 parallel verbindings terselfdertyd ondersteun (en hierdie getal kan verbeter word).

Support HackTricks

Last updated