Ich würde diese Änderung per se nicht als "kritisch" bezeichnen, aber sie hat immer noch Auswirkungen auf die Sicherheit. Mir ist nichts bekannt, was sich grundlegend geändert hat, seit dieser Rat relevant wurde – das Verhalten von PHP tendiert stark in Richtung Abwärtskompatibilität, selbst wenn dies Auswirkungen auf die Sicherheit hat. Stellen Sie sich vor, Sie haben einen Server, der es Leuten erlaubt, Dateien auf den Server hochzuladen, sagen wir in ein Verzeichnis namens upload
. Jetzt achtet Ihr Upload-Skript darauf, nur Dateien mit bestimmten Erweiterungen zuzulassen (z. B. nur .png
), um sicherzustellen, dass niemand eine schädliche PHP-Datei hochlädt.
Als Angreifer versuche ich jetzt, eine PHP-Shell in eine Datei zu schreiben, nenne die Datei evil.png
, und lade es hoch. Wenn es hochgeladen wird, besuche ich http://example.com/upload/evil.png
, aber ich werde feststellen, dass dies die Datei nur zu mir herunterlädt – nginx hat die Anfrage nie an php-fcgi gesendet, um als php verarbeitet zu werden, weil der Dateiname auf .png
endet .
Wenn ich ein Angreifer bin, der PATH_INFO
kennt , als nächstes versuche ich http://example.com/upload/evil.png/index.php
. Wenn Ihr Server so konfiguriert ist, führt dies dazu, dass PHP ausgeführt wird (weil nginx den index.php
sieht am Ende) und PHP wird den Pfad durchlaufen, bis es eine Komponente findet, die eine Datei und kein Verzeichnis ist (evil.png
) und versuchen, es auszuführen. Dann wird meine Shell ausgeführt und ich gewinne.
Abgesehen davon gibt es bessere Möglichkeiten, damit umzugehen, indem die NGINX-Konfiguration den Pfad im Voraus aufteilt, sodass PHP nicht durch das Dateisystem läuft.
Aus Neal Pooles ausgezeichnetem Blogbeitrag zu diesem Thema:
# 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;
}
Selbst jetzt scheint es gefährlich zu sein, weil PHP immer noch Skripte vom ersten Auftreten einer gefundenen Datei verarbeitet. Warum haben sie den Standardwert als ;cgi.fix_pathinfo=1
beibehalten? dann?
Denn CGI ist unabhängig von PHP und hat einen eigenen Standard. CGI (Common Gateway Interface) ist eine Schnittstelle, die den Server anweist, wie Daten mit Anwendungen zu kommunizieren sind, wie Anforderungsinformationen und Text von der Eingabe zur Ausgabe weitergegeben werden. Web-Server können so konfiguriert werden, dass sie ein Programm als CGI
ausführen , was bedeutet, dass sie die Anfragedaten an ein bestimmtes Programm weiterleiten. Und so leitet NGinx die Anfrage an PHP weiter.
Apropos CGI-Standard , PHP-FPM
Entwickler müssen den CGI-Standard einhalten, wie sie in PHP-FPM
angegeben sind ini-Datei Bsp.:/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
Ich nehme also den Text 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.
an erklärt die Auswahl. Hier ist der PATH_INFO
CGI-Spezifikation.