PHP Tricks
Česta lokacija kolačića:
Ovo važi i za kolačiće phpMyAdmin-a.
Kolačići:
Lokacije:
Zaobilaženje PHP poredjenja
Labava poredjenja/Tip Juggling ( == )
Ako se koristi ==
u PHP-u, mogu se pojaviti neočekivani slučajevi gde poredjenje ne radi kako se očekuje. To je zato što "==" uporedjuje samo vrednosti transformisane u isti tip, ako želite da uporedite i da li je tip uporedjenih podataka isti, treba koristiti ===
.
Tabele za poredjenje u PHP-u: 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 heks formatu mogu biti uporedjeni sa drugim brojevima/stringovima sa True rezultatom ako su brojevi isti (brojevi u stringu se interpretiraju kao brojevi)"0e3264578" == 0 --> True
String koji počinje sa "0e" i sledi bilo šta će biti jednak 0"0X3264578" == 0X --> True
String koji počinje sa "0" i sledi bilo koje slovo (X može biti bilo koje slovo) i sledi bilo šta će biti jednak 0"0e12334" == "0" --> True
Ovo je veoma interesantno jer u nekim slučajevima možete kontrolisati string unos "0" i neki sadržaj koji se hešira i uporedjuje sa njim. Stoga, ako možete pružiti vrednost koja će kreirati heš koji počinje sa "0e" i bez bilo kog slova, možete zaobići poredjenje. Možete pronaći već heširane stringove sa ovim formatom ovde: https://github.com/spaze/hashes"X" == 0 --> True
Bilo koje slovo u stringu je jednako int 0
Više informacija na https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
in_array()
Tip Juggling takođe utiče na funkciju in_array()
po default-u (treba postaviti na true treći argument da bi se napravilo strogo poredjenje):
strcmp()/strcasecmp()
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:
Stroga vrsta prebacivanja
Čak i ako se koristi ===
, mogu se pojaviti greške koje čine poređenje ranjivim na vrstu prebacivanja. Na primer, ako poređenje konvertuje podatke u drugačiji tip objekta pre poređenja:
preg_match(/^.*/)
preg_match()
može se koristiti za validaciju korisničkog unosa (proverava da li je bilo koja reč/regex iz crne liste prisutna u korisničkom unosu i ako nije, kod može nastaviti svoje izvršavanje).
Zaobilaženje nove linije
Međutim, kada se deliminiše početak regexp-a, preg_match()
proverava samo prvu liniju korisničkog unosa, pa ako na neki način možete poslati unos u nekoliko linija, možete zaobići ovu proveru. Primer:
Da biste zaobišli ovu proveru, možete poslati vrednost sa novim linijama url-kodiranu (%0A
) ili, ako možete poslati JSON podatke, pošaljite ih u nekoliko linija:
Pronađite primer ovde: https://ramadistra.dev/fbctf-2019-rceservice
Bajpasovanje greške dužine
(Ovaj bajpas je navodno pokušan na PHP 5.2.5 i nisam uspeo da ga pokrenem na PHP 7.3.15)
Ako možete poslati preg_match()
validan veoma veliki unos, on neće moći da ga obradi i moći ćete da bajpasujete proveru. Na primer, ako je na crnoj listi JSON, možete poslati:
ReDoS Bypass
Trik sa: 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 zbog toga što funkcije preg_*
u PHP-u zavise od PCRE biblioteke. U PCRE određeni regularni izrazi se podudaraju korišćenjem velikog broja rekurzivnih poziva, što troši puno stack prostora. Moguće je postaviti ograničenje na broj dozvoljenih rekurzija, ali u PHP-u to ograničenje podrazumevano iznosi 100.000 što je više nego što stane u stack.
U ovom Stackoverflow thread-u takođe je povezan u postu gde se detaljnije govori o ovom problemu. Naš zadatak je sada bio jasan:
Poslati unos koji će naterati regex da izvrši 100_000+ rekurzija, izazivajući SIGSEGV, čineći da funkcija preg_match()
vrati false
, čime aplikacija misli da naš unos nije zlonameran, bacajući iznenađenje na kraju payload-a nešto poput {system(<veomazla naredba>)}
da bismo dobili SSTI --> RCE --> zastavica :).
Pa, u regex terminima, zapravo ne radimo 100k "rekurzija", već brojimo "korake povratka", što, kako PHP dokumentacija navodi, podrazumevano iznosi 1_000_000 (1M) u promenljivoj pcre.backtrack_limit
.
Da bismo to postigli, 'X'*500_001
će rezultirati sa 1 milion koraka povratka (500k unapred i 500k unazad):
Tipovanje tipova za zamagljivanje PHP-a
Izvrši nakon preusmeravanja (EAR)
Ako PHP preusmerava na drugu stranicu, ali nijedna funkcija die
ili exit
nije pozvana nakon postavljanja zaglavlja Location
, PHP nastavlja izvršavanje i dodaje podatke u telo:
Iskorišćavanje putanje pretrage i uključivanje datoteka
Proverite:
pageFile Inclusion/Path traversalViše trikova
register_globals: U PHP < 4.1.1.1 ili ako je loše konfigurisan, register_globals može biti aktivan (ili se njihovo ponašanje oponaša). Ovo implicira da u globalnim promenljivima poput $_GET, ako imaju vrednost npr. $_GET["param"]="1234", možete pristupiti tome 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 se unutar domene koriste različiti kolačići u različitim putanjama možete napraviti da jedna putanja pristupi kolačiću putanje postavljajući vrednost kolačića druge putanje. Na ovaj način, ako obe putanje pristupaju promenljivoj istog imena možete napraviti da vrednost te promenljive u putanji1 važi za putanju2. Zatim će putanja2 smatrati važećim promenljive putanje1 (dajući kolačiću ime koje odgovara putanji2).
Kada imate korisnička imena korisnika mašine. Proverite adresu: /~<USERNAME> da biste videli da li su php direktorijumi aktivirani.
password_hash/password_verify
Ove funkcije se obično koriste u PHP-u za generisanje heševa iz lozinki i za proveru da li je lozinka ispravna 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. Trenutno, PASSWORD_BCRYPT ima ograničenje veličine ulaza od 72 bajta. Stoga, kada pokušate da hešujete nešto veće od 72 bajta ovim algoritmom, koristiće se samo prvih 72B:
Zaobilaženje HTTP zaglavlja zloupotrebom PHP grešaka
Ako PHP stranica ispisuje greške i vraća neke korisnički unete podatke, korisnik može naterati PHP server da vrati neki sadržaj dovoljno dug tako da kada pokuša dodati 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 modifikovati informacije zaglavlja, nije mogao (tako da na primer CSP zaglavlje nije poslato korisniku):
Izvršenje koda
system("ls"); `ls`; shell_exec("ls");
Pogledajte ovo za više korisnih PHP funkcija
RCE putem preg_replace()
Da bi se izvršio kod u "replace" argumentu, potrebno je imati barem jedno poklapanje. Ova opcija preg_replace funkcije je zastarela od PHP 5.5.0.
RCE putem Eval()
RCE putem Assert()
Ova funkcija unutar php-a vam omogućava da izvršite kod koji je napisan u stringu kako biste vratili tačno ili netačno (i u zavisnosti od toga izmenili izvršenje). Obično će korisnička promenljiva biti umetnuta usred stringa. Na primer:
assert("strpos($_GET['page']),'..') === false")
--> U ovom slučaju da biste dobili RCE možete uraditi:
Potrebno je prekinuti sintaksu koda, dodati svoj payload, a zatim je ponovo popraviti. Možete koristiti logičke operacije poput "and" ili "%26%26" ili "|". Imajte na umu da "or", "||" neće raditi jer ako je prvi uslov tačan, naš payload neće biti izvršen. Isto tako, ";" neće raditi jer naš payload neće biti izvršen.
Druga opcija je dodati izvršenje komande u string: '.highlight_file('.passwd').'
Druga opcija (ako imate interni kod) je izmeniti neku promenljivu kako biste promenili izvršenje: $file = "hola"
RCE putem usort()
Ova funkcija se koristi za sortiranje niza stavki pomoću određene funkcije. Da biste zloupotrebili ovu funkciju:
Možete takođe koristiti // da biste komentarisali ostatak koda.
Da biste otkrili broj zagrada koje treba zatvoriti:
?order=id;}//
: dobijamo poruku o grešci (Parse error: syntax error, unexpected ';'
). Verovatno nam nedostaje jedna ili više zagrada.?order=id);}//
: dobijamo upozorenje. To deluje ispravno.?order=id));}//
: dobijamo poruku o grešci (Parse error: syntax error, unexpected ')' i
). Verovatno imamo previše zatvorenih zagrada.
RCE putem .httaccess
Ako možete da otpremite .htaccess, možete konfigurisati nekoliko stvari i čak izvršiti kod (konfigurišući da se fajlovi sa ekstenzijom .htaccess mogu izvršiti).
Različite .htaccess ljuske mogu se pronaći ovde
RCE putem Env promenljivih
Ako pronađete ranjivost koja vam omogućava da modifikujete env promenljive u PHP-u (i još jednu za otpremanje fajlova, mada uz više istraživanja možda se to može zaobići), možete iskoristiti ovaj ponašanje da biste dobili RCE.
LD_PRELOAD
: Ova env promenljiva omogućava vam da učitate proizvoljne biblioteke prilikom izvršavanja drugih binarnih fajlova (mada u ovom slučaju možda neće raditi).PHPRC
: Naređuje PHP-u gde da locira svoj konfiguracioni fajl, obično nazvanphp.ini
. Ako možete otpremiti svoj konfiguracioni fajl, onda koristitePHPRC
da ga usmerite na PHP. Dodajte unosauto_prepend_file
koji navodi drugi otpremljeni fajl. Taj 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š shell kod
Otpremite drugi fajl koji sadrži direktivu
auto_prepend_file
koja naređuje PHP preprocesoru da izvrši fajl koji smo otpremili u koraku 1Postavite promenljivu
PHPRC
na fajl koji smo otpremili u koraku 2.
Dobijte više informacija o tome kako izvršiti ovaj lanac iz originalnog izveštaja.
PHPRC - još jedna opcija
Ako ne možete otpremiti fajlove, možete koristiti u FreeBSD-u "fajl"
/dev/fd/0
koji sadržistdin
, budeći telo zahteva poslatog nastdin
:curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
Ili da biste dobili RCE, omogućite
allow_url_include
i dodajte fajl sa base64 PHP kodom: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=="'
Tehnika iz ovog izveštaja.
PHP Staticna analiza
Pogledajte da li možete ubaciti kod u pozive ovih funkcija (sa ovog):
Ako debagujete PHP aplikaciju, možete globalno omogućiti ispis grešaka u /etc/php5/apache2/php.ini
dodavanjem display_errors = On
i restartovati apache komandom: sudo systemctl restart apache2
Dekodiranje PHP koda
Možete koristiti web www.unphp.net za dekodiranje PHP koda.
PHP omotači i protokoli
PHP omotači i protokoli mogu vam omogućiti da zaobiđete zaštitu od pisanja i čitanja u sistemu i kompromitujete ga. Za više informacija pogledajte ovu stranicu.
Xdebug neautentifikovani RCE
Ako primetite da je Xdebug omogućen u izlazu phpconfig()
, trebalo bi da pokušate da dobijete RCE preko https://github.com/nqxcode/xdebug-exploit
Promenljive promenljivih
RCE zloupotreba novog $_GET["a"]($_GET["b"])
Ako na stranici možete kreirati novi objekat proizvoljne klase, možda ćete moći da dobijete RCE, proverite sledeću stranicu da biste saznali kako:
pagePHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])Izvršavanje PHP-a bez slova
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Korišćenje oktalnog oblika
XOR
XOR jednostavan shell kod
Prema ovom objašnjenju, moguće je generisati jednostavan shell kod na sledeći način:
Dakle, ako možete izvršiti proizvoljni PHP bez brojeva i slova možete poslati zahtev poput sledećeg zloupotrebljavajući taj payload da biste izvršili proizvoljni PHP:
Za detaljnije objašnjenje pogledajte https://ctf-wiki.org/web/php/php/#preg_match
XOR Shellcode (unutar eval)
Perl slično
Last updated