PHP Tricks
Last updated
Last updated
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Kry 'n hacker se perspektief op jou webtoepassings, netwerk, en wolk
Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak. Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, vind sekuriteitskwessies wat jou toelaat om bevoegdhede te verhoog, en gebruik geoutomatiseerde eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
Dit geld ook vir phpMyAdmin koekies.
Koekies:
Ligginge:
As ==
in PHP gebruik word, is daar onverwagte gevalle waar die vergelyking nie soos verwag werk nie. Dit is omdat "==" slegs waardes vergelyk wat na dieselfde tipe omgeskakel is; as jy ook wil vergelyk dat die tipe van die vergelykte data dieselfde is, moet jy ===
gebruik.
PHP vergelykingstabelle: https://www.php.net/manual/en/types.comparisons.php
"string" == 0 -> True
'n String wat nie met 'n nommer begin nie, is gelyk aan 'n nommer
"0xAAAA" == "43690" -> True
Strings wat uit nommers in desimale of hex formaat bestaan, kan met ander nommers/strings vergelyk word met True as resultaat as die nommers dieselfde was (nommers in 'n string word as nommers geïnterpreteer)
"0e3264578" == 0 --> True
'n String wat met "0e" begin en gevolg word deur enigiets, sal gelyk wees aan 0
"0X3264578" == 0X --> True
'n String wat met "0" begin en gevolg word deur enige letter (X kan enige letter wees) en gevolg word deur enigiets, sal gelyk wees aan 0
"0e12334" == "0" --> True
Dit is baie interessant omdat jy in sommige gevalle die stringinvoer van "0" en 'n inhoud wat gehas is en daarmee vergelyk word, kan beheer. Daarom, as jy 'n waarde kan verskaf wat 'n hash kan skep wat met "0e" begin en sonder enige letter, kan jy die vergelyking omseil. Jy kan reeds gehasde strings met hierdie formaat hier vind: https://github.com/spaze/hashes
"X" == 0 --> True
Enige letter in 'n string is gelyk aan int 0
Meer inligting in https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
Tipe Juggling beïnvloed ook die in_array()
funksie standaard (jy moet die derde argument op true stel om 'n strikte vergelyking te maak):
As hierdie funksie gebruik word vir enige outentikasie kontrole (soos om die wagwoord te kontroleer) en die gebruiker een kant van die vergelyking beheer, kan hy 'n leë array in plaas van 'n string as die waarde van die wagwoord stuur (https://example.com/login.php/?username=admin&password[]=
) en hierdie kontrole omseil:
Die dieselfde fout gebeur met strcasecmp()
Selfs al word ===
gebruik, kan daar foute wees wat die vergelyking kwesbaar maak vir tipe juggling. Byvoorbeeld, as die vergelyking die data na 'n ander tipe objek omskakel voordat dit vergelyk:
preg_match()
kan gebruik word om gebruikersinvoer te valideer (dit kontroleer of enige woord/regex van 'n swartlys teenwoordig is in die gebruikersinvoer en as dit nie is nie, kan die kode sy uitvoering voortset).
E however, wanneer die begin van die regexp preg_match()
slegs die eerste lyn van die gebruikersinvoer kontroleer, dan as jy op een of ander manier die invoer in verskeie lyne kan stuur, kan jy dalk hierdie kontrole omseil. Voorbeeld:
Om hierdie kontrole te omseil, kan jy die waarde met nuwe lyne urlencoded stuur (%0A
) of as jy JSON-data kan stuur, stuur dit in verskeie lyne:
Find an example here: https://ramadistra.dev/fbctf-2019-rceservice
(Die omseiling is blykbaar op PHP 5.2.5 probeer en ek kon dit nie laat werk op PHP 7.3.15)
As jy preg_match()
'n geldige baie groot invoer kan stuur, sal dit nie in staat wees om dit te verwerk nie en jy sal in staat wees om die kontrole te omseil. Byvoorbeeld, as dit 'n JSON swartlys, kan jy stuur:
From: https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0
Trick from: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 and https://mizu.re/post/pong
In kort gebeur die probleem omdat die preg_*
funksies in PHP op die PCRE biblioteek bou. In PCRE word sekere gereelde uitdrukkings gematch deur 'n groot aantal rekursiewe oproepe te gebruik, wat baie stapelruimte gebruik. Dit is moontlik om 'n limiet op die aantal toegelate rekursies in te stel, maar in PHP is hierdie limiet standaard op 100.000 wat meer is as wat in die stapel pas.
Hierdie Stackoverflow draad is ook in die pos gekoppel waar daar meer in diepte oor hierdie probleem gepraat word. Ons taak was nou duidelik:
Stuur 'n invoer wat die regex 100_000+ rekursies sal laat doen, wat SIGSEGV veroorsaak, wat die preg_match()
funksie false
laat teruggee, wat die aansoek laat dink dat ons invoer nie kwaadwillig is nie, en die verrassing aan die einde van die payload iets soos {system(<verybadcommand>)}
om SSTI --> RCE --> vlag :).
Wel, in regex terme, doen ons nie eintlik 100k "rekursies" nie, maar eerder tel ons "terugspoel stappe", wat soos die PHP dokumentasie sê, standaard op 1_000_000 (1M) in die pcre.backtrack_limit
veranderlike is.
Om dit te bereik, sal 'X'*500_001
lei tot 1 miljoen terugspoel stappe (500k vorentoe en 500k agtertoe):
As PHP na 'n ander bladsy herlei, maar geen die
of exit
funksie is na die kop Location
gestel nie, gaan die PHP voort om uit te voer en voeg die data by die liggaam:
Kontroleer:
File Inclusion/Path traversalregister_globals: In PHP < 4.1.1.1 of as verkeerd geconfigureer, kan register_globals aktief wees (of hul gedrag word nagebootst). Dit impliseer dat in globale veranderlikes soos $_GET as hulle 'n waarde het bv. $_GET["param"]="1234", kan jy dit toegang via $param. Daarom, deur HTTP parameters te stuur kan jy veranderlikes wat binne die kode gebruik word oorskryf.
Die PHPSESSION koekies van dieselfde domein word in dieselfde plek gestoor, daarom as binne 'n domein verskillende koekies in verskillende paaie gebruik word kan jy maak dat 'n pad die koekie van die pad toegang gee deur die waarde van die ander pad koekie in te stel. Op hierdie manier, as albei paaie toegang het tot 'n veranderlike met dieselfde naam kan jy maak dat die waarde van daardie veranderlike in pad1 van toepassing is op pad2. En dan sal pad2 die veranderlikes van pad1 as geldig neem (deur die koekie die naam te gee wat ooreenstem met dit in pad2).
Wanneer jy die gebruikersname van die gebruikers van die masjien het. Kontroleer die adres: /~<USERNAME> om te sien of die php gidse geaktiveer is.
Hierdie funksies word tipies in PHP gebruik om hashes van wagwoorde te genereer en om te kontroleer of 'n wagwoord korrek is in vergelyking met 'n hash.
Die ondersteunde algoritmes is: PASSWORD_DEFAULT
en PASSWORD_BCRYPT
(begin met $2y$
). Let daarop dat PASSWORD_DEFAULT dikwels dieselfde is as PASSWORD_BCRYPT. En tans het PASSWORD_BCRYPT 'n grootte beperking in die invoer van 72bytes. Daarom, wanneer jy probeer om iets groter as 72bytes met hierdie algoritme te hash, sal slegs die eerste 72B gebruik word:
Van hierdie twitter draad kan jy sien dat wanneer meer as 1000 GET params of 1000 POST params of 20 lêers gestuur word, PHP nie headers in die antwoord gaan instel nie.
Dit laat toe om byvoorbeeld CSP headers te omseil wat in kodes soos:
As 'n PHP-bladsy foute druk en sommige invoer wat deur die gebruiker verskaf is, teruggee, kan die gebruiker die PHP-bediener dwing om 'n inhoud lank genoeg te druk sodat wanneer dit probeer om die koptekste in die antwoord by te voeg, die bediener 'n fout sal gooi. In die volgende scenario het die aanvaller die bediener gedwing om groot foute te gooi, en soos jy in die skerm kan sien, toe php probeer het om die koptekst-inligting te wysig, kon dit nie (soos byvoorbeeld die CSP-koptekst nie aan die gebruiker gestuur is nie):
Kyk na die bladsy:
PHP SSRFsystem("ls"); `ls`; shell_exec("ls");
Kontroleer dit vir meer nuttige PHP-funksies
Om die kode in die "replace" argument uit te voer, is ten minste een ooreenkoms nodig. Hierdie opsie van preg_replace is verouderd sedert PHP 5.5.0.
Hierdie funksie binne php laat jou toe om kode wat in 'n string geskryf is te uitvoer om waar of vals te terug te gee (en afhangende hiervan die uitvoering te verander). Gewoonlik sal die gebruikersvariabele in die middel van 'n string ingevoeg word. Byvoorbeeld:
assert("strpos($_GET['page']),'..') === false")
--> In hierdie geval om RCE te verkry kan jy doen:
U sal die kode sintaksis moet breek, u payload byvoeg, en dan weer regmaak. U kan logiese operasies soos "and" of "%26%26" of "|" gebruik. Let daarop dat "or", "||" nie werk nie, want as die eerste voorwaarde waar is, sal ons payload nie uitgevoer word nie. Dieselfde geld ";" wat nie werk nie, aangesien ons payload nie uitgevoer sal word nie.
Ander opsie is om die uitvoering van die opdrag aan die string toe te voeg: '.highlight_file('.passwd').'
Ander opsie (as u die interne kode het) is om 'n paar veranderlikes te wysig om die uitvoering te verander: $file = "hola"
Hierdie funksie word gebruik om 'n reeks items te sorteer met behulp van 'n spesifieke funksie. Om hierdie funksie te misbruik:
You can also use // to comment the rest of the code.
To discover the number of parenthesis that you need to close:
?order=id;}//
: ons kry 'n foutboodskap (Parse error: syntax error, unexpected ';'
). Ons mis waarskynlik een of meer hakies.
?order=id);}//
: ons kry 'n waarskuwing. Dit lyk reg.
?order=id));}//
: ons kry 'n foutboodskap (Parse error: syntax error, unexpected ')' i
). Ons het waarskynlik te veel sluitende hakies.
If you can upload a .htaccess, then you can configure several things and even execute code (configuring that files with extension .htaccess can be executed).
Different .htaccess shells can be found here
If you find a vulnerability that allows you to modify env variables in PHP (and another one to upload files, although with more research maybe this can be bypassed), you could abuse this behaviour to get RCE.
LD_PRELOAD
: Hierdie omgewingsvariabele laat jou toe om arbitrêre biblioteke te laai wanneer jy ander binaire uitvoer (alhoewel dit in hierdie geval dalk nie sal werk nie).
PHPRC
: Gee PHP instruksies oor waar om sy konfigurasie-lêer te vind, wat gewoonlik php.ini
genoem word. As jy jou eie konfigurasie-lêer kan oplaai, gebruik dan PHPRC
om PHP daarop te wys. Voeg 'n auto_prepend_file
inskrywing by wat 'n tweede opgelaaide lêer spesifiseer. Hierdie tweede lêer bevat normale PHP-kode, wat dan uitgevoer word deur die PHP-runtime voordat enige ander kode.
Laai 'n PHP-lêer op wat ons shellcode bevat
Laai 'n tweede lêer op, wat 'n auto_prepend_file
riglyn bevat wat die PHP-preprocessor instrueer om die lêer wat ons in stap 1 opgelaai het, uit te voer
Stel die PHPRC
-variabele in op die lêer wat ons in stap 2 opgelaai het.
Kry meer inligting oor hoe om hierdie ketting uit te voer uit die oorspronklike verslag.
PHPRC - 'n ander opsie
As jy nie lêers kan oplaai nie, kan jy in FreeBSD die "lêer" /dev/fd/0
gebruik wat die stdin
bevat, wat die liggaam van die versoek is wat na die stdin
gestuur is:
curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
Of om RCE te kry, stel allow_url_include
in en voeg 'n lêer met base64 PHP-kode voor:
curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'
Tegniek uit hierdie verslag.
The webserver parses HTTP requests and passes them to a PHP script executing a request such as as http://host/cgi.php?foo=bar
as php.exe cgi.php foo=bar
, which allows a parameter injection. This would allow to inject the following parameters to load the PHP code from the body:
Boonop, dit is moontlik om die "-" param te injekteer met die 0xAD karakter as gevolg van latere normalisering van PHP. Kyk na die eksploit voorbeeld van hierdie pos:
In hierdie pos is dit moontlik om wonderlike idees te vind om 'n brain fuck PHP-kode te genereer met baie min karakters wat toegelaat word. Boonop word daar ook 'n interessante manier voorgestel om funksies uit te voer wat hulle in staat gestel het om verskeie kontroles te omseil:
Kyk of jy kode kan invoeg in oproepe na hierdie funksies (van hier):
As jy 'n PHP-toepassing aan die debug is, kan jy globaal foutdrukking aktiveer in /etc/php5/apache2/php.ini
deur display_errors = On
by te voeg en apache te herbegin: sudo systemctl restart apache2
Jy kan die web www.unphp.net gebruik om php-kode te deobfuskeer.
PHP Wrappers en protokolle kan jou toelaat om skrywe en lees beskermings in 'n stelsel te omseil en dit te kompromitteer. Vir meer inligting, kyk na hierdie bladsy.
As jy sien dat Xdebug geaktiveer is in 'n phpconfig()
uitvoer, moet jy probeer om RCE te verkry via https://github.com/nqxcode/xdebug-exploit
As jy op 'n bladsy 'n nuwe objek van 'n arbitrêre klas kan skep, mag jy in staat wees om RCE te verkry, kyk na die volgende bladsy om te leer hoe:
PHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Volgens hierdie skrywe is dit moontlik om 'n maklike shellkode op hierdie manier te genereer:
So, as jy arbitraire PHP kan uitvoer sonder nommers en letters kan jy 'n versoek soos die volgende stuur wat daardie payload misbruik om arbitraire PHP uit te voer:
Vir 'n meer diepgaande verduideliking, kyk https://ctf-wiki.org/web/php/php/#preg_match
Kry 'n hacker se perspektief op jou webtoepassings, netwerk en wolk
Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak. Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, sekuriteitskwessies te vind wat jou toelaat om bevoegdhede te verhoog, en gebruik geoutomatiseerde eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskakel.
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)