Frage Ist die PHP-Option 'cgi.fix_pathinfo' mit Nginx + PHP-FPM wirklich gefährlich?


Da war ein  Menge  von  reden über ein Sicherheitsproblem in Bezug auf die cgi.fix_pathinfo PHP-Option, die mit Nginx verwendet wird (normalerweise PHP-FPM, schnelles CGI).

Daher verwendete die standardmäßige Nginx-Konfigurationsdatei Folgendes:

# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

Nun aber, das "offizielle" Nginx-Wiki besagt, dass PATH_INFO kann korrekt behandelt werden, ohne die obige PHP-Option zu deaktivieren. Na und?

Fragen

  • Kannst du klar erklären was? cgi.fix_pathinfo tun? (offizielles Dokument sagt nur: "Weitere Informationen zu PATH_INFO finden Sie in den CGI-Spezifikationen")
  • Was wird PHP wirklich damit machen? PATH_INFO und SCRIPT_FILENAME Variablen?
  • Warum und wie kann es mit Nginx gefährlich sein? (detailliert Beispiele)
  • Ist das Problem in den letzten Versionen dieser Programme noch vorhanden?
  • Ist Apache anfällig?

Ich versuche das Problem bei jedem Schritt zu verstehen. Zum Beispiel verstehe ich nicht, warum der php-fpm Unix-Socket verwendet wird könnte vermeiden dieses Problem.


40
2017-09-11 17:35


Ursprung


Sie können Ihre eigene Frage beantworten, indem Sie den Unterschied zwischen PATH_INFO und PATH_TRANSLATED verstehen: blogs.msdn.com/b/david.wang/archiv/2005/08/04/... - Giovanni Tirloni


Antworten:


TL, DR - das Update (das Sie vielleicht nicht einmal brauchen) ist sehr einfach und am Ende dieser Antwort.

Ich werde versuchen, Ihre spezifischen Fragen zu beantworten, aber Ihr Missverständnis darüber, was PATH_INFO ist, macht die Fragen selbst ein wenig falsch.

  • Die erste Frage sollte sein: "Was ist das Pfadinfo-Geschäft?"

  • Ihre nächste Frage sollte lauten: "Wie ermittelt PHP was? PATH_INFO und SCRIPT_FILENAME sind?"

    • Frühere Versionen von PHP waren naiv und technisch nicht einmal unterstützt PATH_INFOAlso, was sollte sein PATH_INFO wurde munged auf SCRIPT_FILENAME was ja in vielen Fällen kaputt ist. Ich habe keine alt genug Version von PHP, um mit zu prüfen, aber ich glaube, dass es gesehen hat SCRIPT_FILENAME als den ganzen shebang: "/path/to/script.php/THIS/IS/PATH/INFO" im obigen Beispiel (vorangestellt mit dem Docroot wie üblich).
    • Wenn cgi.fix_pathinfo aktiviert ist, findet PHP jetzt korrekt "/ THIS / IS / PATH / INFO" für das obige Beispiel und fügt es ein PATH_INFO und SCRIPT_FILENAME Ruft nur den Teil ab, der auf das angeforderte Skript verweist (dem Docroot vorangestellt ist).
    • Hinweis: Als PHP dazu kam, tatsächlich zu unterstützen PATH_INFOSie mussten eine Konfigurationseinstellung für die neue Funktion hinzufügen, damit Benutzer, die Skripts ausführen, die vom alten Verhalten abhängig waren, neue PHP-Versionen ausführen konnten. Deshalb gibt es sogar einen Konfigurationsschalter dafür. Es sollte von Anfang an (mit dem "gefährlichen" Verhalten) eingebaut sein.
  • Aber wie weiß PHP, welcher Teil das Skript ist und was es Pfadinformationen? Was ist, wenn der URI etwa so aussieht:

    http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo

    • Das kann in manchen Umgebungen eine komplexe Frage sein. Was in PHP passiert ist, dass es den ersten Teil des URI-Pfades findet, der nichts unter der Docroot des Servers entspricht. Für dieses Beispiel sieht es, dass Sie auf Ihrem Server nicht "/docroot/path/to/script.php/THIS" haben, aber Sie haben sicherlich "/docroot/path/to/script.php", also jetzt SCRIPT_FILENAME wurde festgestellt und PATH_INFO bekommt den Rest.
    • Nun also das gute Beispiel der Gefahr, die in den Nginx - Dokumenten und in Hrvoje Špoljars Antwort (Sie können nicht über so ein klares Beispiel pingelig sein) wird noch klarer: gegeben Hrvojes Beispiel ("http://example.com/foo.jpg/nonexistent.php "), PHP sieht eine Datei auf Ihrer Docroot" /foo.jpg ", aber es sieht nichts" /foo.jpg/nonexistent.php "so SCRIPT_FILENAME erhält "/foo.jpg" (wieder mit Docroot vorangestellt) und PATH_INFO erhält "/nonexistent.php".
  • Warum und wie es gefährlich sein kann, sollte jetzt klar sein:

    • Der Webserver ist wirklich nicht schuld - es ist nur Proxy der URI zu PHP, die unschuldig findet, dass "foo.jpg" tatsächlich PHP-Inhalt enthält, so dass es ausgeführt wird (jetzt sind Sie pwned!). Das ist NICHT insbesondere für Nginx an sich.
  • Das ECHT Problem ist, dass Sie nicht vertrauenswürdigen Inhalt irgendwo ohne Desinfektion hochladen lassen und andere willkürliche Anfragen an denselben Ort erlauben, den PHP gerne ausführt, wenn es möglich ist.
  • Nginx und Apache könnten so aufgebaut oder konfiguriert werden, dass Anfragen mit dieser Trickserei verhindert werden, und es gibt viele Beispiele dafür, wie man das macht, einschließlich in Benutzer2372674's Antwort. Dieser Blogartikel erklärt das Problem schön, aber es fehlt die richtige Lösung.

  • Die beste Lösung besteht jedoch darin, sicherzustellen, dass PHP-FPM korrekt konfiguriert ist, so dass es niemals eine Datei ausführen wird, wenn sie nicht mit ".php" endet. Es ist erwähnenswert, dass aktuelle Versionen von PHP-FPM (~ 5.3.9 +?) Dies standardmäßig haben, so dass diese Gefahr nicht mehr so ​​groß ist.

Die Lösung

Wenn Sie eine aktuelle Version von PHP-FPM (~ 5.3.9 +?) Haben, müssen Sie nichts tun, da das unten beschriebene sichere Verhalten bereits der Standard ist.

Ansonsten finde php-fpm's www.conf Datei (vielleicht /etc/php-fpm.d/www.conf, hängt von Ihrem System ab). Stellen Sie sicher, dass Sie Folgendes haben:

security.limit_extensions = .php

Auch das ist an vielen Stellen in diesen Tagen Standard.

Beachten Sie, dass dies einen Angreifer nicht daran hindert, eine ".php" -Datei in einen WordPress-Upload-Ordner hochzuladen und dies mit derselben Technik auszuführen. Sie müssen immer noch eine gute Sicherheit für Ihre Anwendungen haben.


61
2018-06-25 04:09



Gute Antwort! Zur Klarstellung: Wenn, wie Sie sagen, PHP bestimmt was SCRIPT_FILENAME ist, warum gibt es a fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; Linie in meinem nginx conf? Überschreibt es PHPs Bemühungen, den Wert von zu entdecken SCRIPT_FILENAME von selbst? - Totor
Gibt es eine Funktion, um den Wert von zu erhalten? security.limit_extensions? Ich habe es versucht phpinfo(), ini_get(security.limit_extensions), und ini_get_all() ohne Erfolg. - elbowlobstercowstand


Im Wesentlichen ohne dies können Sie Datei mit PHP-Code namens "foo.jpg" auf den Webserver hochladen; dann fordere es gerne an http: //domain.tld/foo.jpg/nonexistent.php und der Webserver-Stack wird fälschlicherweise sagen oh; das ist ein PHP; Ich muss das verarbeiten, es wird foo.jpg / nonexistent.php nicht finden, also wird es auf foo.jpg zurückgreifen und foo.jpg als PHP-Code verarbeiten. Das ist gefährlich, da es das System zu sehr leichtem Eindringen öffnet; Jede Web-Anwendung, die beispielsweise Bild-Uploads ermöglicht, wird zum Laden von Hintertüren.

In Bezug auf die Verwendung von PHP-FPM mit Unix-Socket, um es zu vermeiden; IMO wird das Problem nicht lösen.


12
2017-09-12 10:04



Sie wiederholen nur, was auf den von mir bereitgestellten Links gelesen werden kann. Sie erklären nicht den wirklichen Mechanismus. Ihre Antwort braucht einen Mehrwert IMHO. - Totor
Das mag stimmen, aber Ihr Titel hat eine Frage und Antwort auf diese Frage in meiner Antwort. Wenn Sie es explizit wollen; Ja, es ist gefährlich; sehr gefährlich. - Hrvoje Špoljar
1 / Meine Antwort beschränkt sich nicht auf den Titel: Es hat einen Körper. 2 / Benutzer109322 hat dir falsch bewiesen: welcher Wert auch immer verwendet cgi.fix_pathinfo ist nicht gefährlich, weil der Standardkonf von php-fpm ist sicher (es wird nur Dateien mit dem ausführen .php Erweiterung). - Totor


In dem Nginx Wiki als Sicherheitsmaßnahme

if (!-f $document_root$fastcgi_script_name) {
    return 404;
}

ist im Standortblock enthalten. In anderen Tutorials

try_files $uri =404;

verwendet wird, das sollte das gleiche tun, kann aber Probleme nach dem Nginx-Wiki ergeben. Mit diesen Optionen cgi.fix_pathinfo=1 sollte kein Problem mehr sein. Weitere Informationen finden Sie Hier.


1
2018-06-24 13:47