7.9 KiB
LFI2RCE tramite Eternal waiting
Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF Controlla i PACCHETTI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale di PEASS & HackTricks
- Scopri The PEASS Family, la nostra collezione di esclusive NFT
- Unisciti al 💬 gruppo Discord o al gruppo Telegram o seguici su Twitter 🐦 @carlospolopm.
- Condividi i tuoi trucchi di hacking inviando PR a HackTricks e HackTricks Cloud github repos.
Informazioni di base
Per impostazione predefinita, quando un file viene caricato su PHP (anche se non lo si aspetta), verrà generato un file temporaneo in /tmp
con un nome come php[a-zA-Z0-9]{6}
, anche se ho visto alcune immagini docker in cui i file generati non contengono cifre.
In una inclusione di file locale, se riesci a includere quel file caricato, otterrai RCE.
Nota che per impostazione predefinita PHP consente di caricare solo 20 file in una singola richiesta (impostato in /etc/php/<version>/apache2/php.ini
):
; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20
Inoltre, il numero di possibili nomi di file è 62*62*62*62*62*62 = 56800235584
Altre tecniche
Altre tecniche si basano sull'attacco ai protocolli PHP (non sarà possibile se si controlla solo l'ultima parte del percorso), sulla divulgazione del percorso del file, sfruttando file attesi o causando un errore di segmentazione in PHP in modo che i file temporanei caricati non vengano eliminati.
Questa tecnica è molto simile all'ultima, ma senza la necessità di trovare una vulnerabilità zero day.
Tecnica dell'attesa eterna
In questa tecnica abbiamo solo bisogno di controllare un percorso relativo. Se riusciamo a caricare file e a far sì che l'LFI non finisca mai, avremo "abbastanza tempo" per forzare la ricerca dei file caricati e trovare quelli che sono stati caricati.
Vantaggi di questa tecnica:
- È sufficiente controllare un percorso relativo all'interno di un include
- Non richiede nginx o un livello di accesso inaspettato ai file di log
- Non richiede una vulnerabilità zero day per causare un errore di segmentazione
- Non richiede la divulgazione del percorso
I principali problemi di questa tecnica sono:
- È necessario che un file specifico (potrebbero essercene altri) sia presente
- L'enorme quantità di possibili nomi di file: 56800235584
- Se il server non utilizza cifre, la quantità totale potenziale è: 19770609664
- Per impostazione predefinita, è possibile caricare solo 20 file in una singola richiesta.
- Il numero massimo di worker paralleli del server utilizzato.
- Questo limite insieme ai precedenti può far durare troppo a lungo l'attacco
- Timeout per una richiesta PHP. Idealmente dovrebbe essere eterno o dovrebbe terminare il processo PHP senza eliminare i file temporanei caricati, altrimenti anche questo sarà un problema
Quindi, come si può far sì che un include PHP non finisca mai? Semplicemente includendo il file /sys/kernel/security/apparmor/revision
(sfortunatamente non disponibile nei container Docker).
Provalo chiamando semplicemente:
php -a # open php cli
include("/sys/kernel/security/apparmor/revision");
Apache2
Di default, Apache supporta 150 connessioni simultanee, seguendo https://ubiq.co/tech-blog/increase-max-connections-apache/ è possibile aumentare questo numero fino a 8000. Segui questo per utilizzare PHP con quel modulo: https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04.
Di default, (come posso vedere nei miei test), un processo PHP può durare all'infinito.
Facciamo un po' di matematica:
- Possiamo utilizzare 149 connessioni per generare 149 * 20 = 2980 file temporanei con la nostra webshell.
- Quindi, utilizza l'ultima connessione per forzare potenziali file.
- Ad una velocità di 10 richieste/s i tempi sono:
- 56800235584 / 2980 / 10 / 3600 ~= 530 ore (50% di probabilità in 265h)
- (senza cifre) 19770609664 / 2980 / 10 / 3600 ~= 185h (50% di probabilità in 93h)
{% hint style="warning" %} Nota che nell'esempio precedente stiamo completamente DoSando altri client! {% endhint %}
Se il server Apache viene migliorato e potremmo abusare di 4000 connessioni (a metà strada verso il numero massimo). Potremmo creare 3999*20 = 79980
file e il numero sarebbe ridotto a circa 19.7h o 6.9h (10h, 3.5h 50% di probabilità).
PHP-FMP
Se invece di utilizzare il modulo php regolare per apache per eseguire gli script PHP, la pagina web sta utilizzando PHP-FMP (questo migliora l'efficienza della pagina web, quindi è comune trovarlo), c'è qualcos'altro che può essere fatto per migliorare la tecnica.
PHP-FMP permette di configurare il parametro request_terminate_timeout
in /etc/php/<php-version>/fpm/pool.d/www.conf
.
Questo parametro indica il numero massimo di secondi quando la richiesta a PHP deve terminare (infinito per impostazione predefinita, ma 30s se il parametro è scommentato). Quando una richiesta viene elaborata da PHP per il numero di secondi indicato, viene terminata. Ciò significa che se la richiesta stava caricando file temporanei, perché l'elaborazione di php è stata interrotta, quei file non verranno eliminati. Pertanto, se puoi far durare una richiesta quel tempo, puoi generare migliaia di file temporanei che non verranno eliminati, il che accelera il processo di ricerca e riduce la probabilità di un DoS alla piattaforma consumando tutte le connessioni.
Quindi, per evitare il DoS supponiamo che un attaccante utilizzerà solo 100 connessioni contemporaneamente e il tempo massimo di elaborazione di php-fmp (request_terminate_timeout
) è di 30s. Pertanto, il numero di file temporanei che possono essere generati al secondo è 100*20/30 = 66.67
.
Quindi, per generare 10000 file un attaccante avrebbe bisogno di: 10000/66.67 = 150s
(per generare 100000 file il tempo sarebbe di 25 minuti).
Quindi, l'attaccante potrebbe utilizzare quelle 100 connessioni per eseguire una ricerca brute-force. Supponendo una velocità di 300 req/s il tempo necessario per sfruttare ciò è il seguente:
- 56800235584 / 10000 / 300 / 3600 ~= 5.25 ore (50% di probabilità in 2.63h)
- (con 100000 file) 56800235584 / 100000 / 300 / 3600 ~= 0.525 ore (50% di probabilità in 0.263h)
Sì, è possibile generare 100000 file temporanei in un'istanza di dimensioni medie di EC2:
![](/Mirrors/hacktricks/media/commit/d03487fb27328ed581616e88b7ed4805962c128b/.gitbook/assets/image%20%283%29%20%281%29%20%281%29%20%283%29.png)
{% hint style="warning" %} Nota che per attivare il timeout sarebbe sufficiente includere la pagina LFI vulnerabile, in modo che entri in un ciclo di inclusione eterno. {% endhint %}
Nginx
Sembra che di default Nginx supporti 512 connessioni parallele contemporaneamente (e questo numero può essere migliorato).