Non descriverei questo cambiamento come "critico" di per sé, ma ha comunque implicazioni sulla sicurezza. Non sono a conoscenza di nulla che sia cambiato radicalmente da quando quel consiglio è diventato rilevante:il comportamento di PHP tende fortemente alla compatibilità con le versioni precedenti, anche quando ciò ha implicazioni sulla sicurezza. Immagina di avere un server che consente alle persone di caricare file sul server, diciamo in una directory chiamata upload
. Ora, il tuo script di caricamento è attento a consentire solo file con determinate estensioni (diciamo solo .png
) per garantire che nessuno carichi un file PHP dannoso.
Ora, come utente malintenzionato, proverò a scrivere una shell PHP in un file, chiamandolo evil.png
e caricalo. Quando verrà caricato, visiterò http://example.com/upload/evil.png
, ma scoprirò che questo scarica solo il file per me -- nginx non ha mai inviato la richiesta a php-fcgi per essere elaborato come php, perché il nome del file termina con .png
.
Se sono un utente malintenzionato che è a conoscenza di PATH_INFO
, poi proverò http://example.com/upload/evil.png/index.php
. Se il tuo server è così configurato, ciò comporterà l'esecuzione di PHP (poiché nginx vede il index.php
alla fine) e PHP percorrerà il percorso finché non troverà un componente che è un file, non una directory (evil.png
) e tentare di eseguirlo. Quindi la mia shell viene eseguita e io vinco.
Detto questo, ci sono modi migliori per affrontare questo problema facendo in modo che la configurazione di NGINX suddivida il percorso in anticipo, in modo che PHP non percorra il filesystem.
Dall'eccellente post sul blog di Neal Poole sull'argomento:
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php;
}
Anche ora sembra comportare un pericolo a causa del modo in cui PHP sta ancora elaborando lo script dalla prima occorrenza del file trovato. Allora perché hanno mantenuto il valore predefinito come ;cgi.fix_pathinfo=1
allora?
Perché CGI è indipendente da PHP e ha il proprio standard. CGI (Common Gateway Interface) è un'interfaccia che istruisce il server su come comunicare i dati con le applicazioni, come vengono passate le informazioni e il corpo della richiesta, dall'input all'output. I server del Web possono essere configurati per eseguire un programma come CGI
, il che significa che inoltreranno i dati della richiesta a un programma specifico. Ed è così che NGinx passa la richiesta a PHP.
A proposito di Standard CGI , PHP-FPM
gli sviluppatori devono rispettare lo standard CGI come indicato nel PHP-FPM
ini ex :/etc/php/7.2/fpm/php.ini
:
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
; http://php.net/cgi.fix-pathinfo
;cgi.fix_pathinfo=1
Quindi suppongo che il testo Setting this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting of zero causes PHP to behave as before.
spiega la scelta. Ecco il PATH_INFO
Specifiche CGI.