PHP Handbuch
Zurück | Kapitel 5. Sicherheit | Nach vorne

# CGI-Version

## Mögliche Angriffe

PHP als CGI zu nutzen, ist eine Möglichkeit für Installationen, bei denen aus irgendwelchen Gründen kein Modul in die Serversoftware eingebunden werden soll (wie beim Apache) oder für Systeme, bei denen verschiedene CGI-Wrapper genutzt werden sollen, um sichere chroot- und setuid-Umgebungen für Skripte zu schaffen. Bei dieser Konfiguration wird das ausführbare PHP-Binary üblicherweise im cgi-bin Verzeichnis des Webservers installiert. CERT advisory CA-96.11 spricht sich gegen die Platzierung von Interpretern im cgi-bin Verzeichnis aus. Obwohl das PHP-Binary als eigenständiger Interpreter verwendet werden kann, wurde PHP so entwickelt, um den durch diese Konfiguration möglich werdenden Angriffe vorzubeugen:

- Zugriff auf Systemdateien: `http://my.host/cgi-bin/php?/etc/passwd`

  Die auf ein Fragezeichen (?) folgende Abfrageinformation in einer URL wird durch das CGI-Interface als Kommandozeilenargument an den Interpreter weitergereicht. In der Kommandozeile wird üblicherweise die im ersten Argument angegebene Datei von Interpretern geöffnet und ausgeführt.

  Beim Aufruf als CGI-Binary verweigert PHP die Interpretation der Kommandozeilenargumente.

- Zugriff auf beliebige Web-Dokumente auf dem Server: `http://my.host/cgi-bin/php/secret/doc.html`

  Der Teil der URL-Pfadinformation nach dem Namen der PHP Binärdatei, `/secret/doc.html` wird im allgemeinen benutzt, um den Namen der Datei zu übergeben, die durch das CGI-Programm geöffnet und interpretiert werden soll. Normalerweise werden einige Einträge in der Konfigurationsdatei des Webservers benutzt (Apache: Action), um Aufrufe von Dokumenten wie `http://my.host/secret/script.php3` an den PHP-Interpreter umzuleiten. Bei dieser Konfiguration überprüft der Webserver zuerst die Zugriffsrechte im Verzeichnis `/secret` und erstellt anschließend den umgeleiteten Aufruf `http://my.host/cgi-bin/php/secret/script.php`. Unglücklicherweise wird, wenn der Aufruf bereits in dieser Form geschieht, vom Webserver keine Zugriffsüberprüfung der Datei `/secret/script.php`, sondern lediglich der Datei `/cgi-bin/php` vorgenommen. So ist jeder Benutzer, der auf `/cgi-bin/php` zugreifen darf in der Lage, sich zu jedem geschützten Dokument auf dem Webserver Zugriff zu verschaffen.

  Bei PHP können beim Kompilieren die Konfigurationsoption --enable-force-cgi-redirect und zur Laufzeit die Konfigurationsdirektiven doc_root und user_dir benutzt werden, um diesen Angriff zu verhindern, falls der Verzeichnisbaum des Servers Verzeichnisse mit Zugriffsbeschränkungen beinhaltet. Ausführliche Informationen über die verschiedenen Kombinationen siehe weiter unten.

## Fall 1: Nur öffentliche Dateien vorhanden

Wenn der Server keine Inhalte hat, die durch Passwort oder IP-basierte Zugriffskontrolle geschützt sind, werden diese Konfigurationsoptionen nicht benötigt. Wenn der Webserver keine Redirects erlaubt oder keine Möglichkeit hat, dem PHP-Binary mitzuteilen dass es sich um eine sicher umgeleitete Anfrage handelt, kann die Option --enable-force-cgi-redirect im configure-Script angegeben werden. Nichtsdestotrotz müssen Sie sicherstellen, dass Ihre PHP-Skripte nicht auf die eine oder andere Art des Aufrufs angewiesen sind, weder direkt durch `http://my.host/cgi-bin/php/dir/script.php` noch durch einen Redirect `http://my.host/dir/script.php`.

Beim Apache kann der Redirect durch den Gebrauch von AddHandler und Action konfiguriert werden (siehe unten).

## Fall 2: --enable-force-cgi-redirect benutzen

Diese beim Kompilieren verwendete Option verhindert grundsätzlich den Aufruf von PHP mit einer URL wie `http://my.host/cgi-bin/php/secretdir/script.php`. Stattdessen parst PHP in diesem Modus nur dann, wenn der Aufruf durch einen korrekten Redirect des Webservers erfolgte.

Normalerweise wird der Redirect in der Apache-Konfiguration mit den folgenden Einträgen festgelegt:

    Action php-script /cgi-bin/php
    AddHandler php-script .php

Diese Option wurde nur mit dem Apache Webserver getestet und ist abhängig davon, wie Apache die nicht standardmäßige CGI-Umgebungsvariable `REDIRECT_STATUS` bei Redirect-Anfragen setzt. Sollte Ihr Webserver keine Möglichkeit unterstützen, zu übermitteln, ob es sich um einen direkte Aufruf oder einen Redirect handelt, können Sie diese Option nicht verwenden und müssen einen der anderen hier beschriebenen Wege gehen, die CGI-Version zu nutzen.

## Fall 3: doc_root oder user_dir festlegen

Aktiven Inhalt, wie beispielsweise Skripts und ausführbare Dateien, in den Dokumentverzeichnissen des Webservers abzulegen, wird manchmal als unsichere Methode angesehen. Wenn, beispielsweise aufgrund von Konfigurationsfehlern, die Skripte nicht ausgeführt, sondern als reguläre HTML-Dokumente angezeigt werden kann dies ein Durchsickern von geistigem Eigentum und sicherheitsrelevanter Informationen (Passwörter!) zur Folge haben. Deshalb ziehen es viele Systemadministratoren vor, eine zweite Verzeichnisstruktur für Skripte einzurichten, auf die nur durch das PHP-CGI zugegriffen werden kann. Diese werden dann stets interpretiert und nicht angezeigt.

Auch wenn die Methode zum sichergestellten Verhindern einer Umleitung von Anfragen (wie im vorangegangenen Kapitel beschrieben) nicht verfügbar ist, ist es notwendig, ein doc_root für Skripte zusätzlich zum Web-Dokumentenverzeichnis einzurichten.

Sie können das PHP-Skriptverzeichnis durch die Direktive doc_root in der Konfigurationsdatei festlegen, oder Sie setzen die Umgebungsvariable `PHP_DOCUMENT_ROOT`. Wenn sie gesetzt ist, wird die CGI-Version von PHP den Namen der zu öffnenden Datei stets aus `doc_root` und der Pfadinformation der Anfrage zusammensetzen, sodass man sicher sein kann, dass außerhalb dieses Verzeichnisses keine Skripte ausgeführt werden (außer `user_dir`, siehe unten).

Eine weitere hier nützliche Option ist user_dir. Wenn das `user_dir` nicht gesetzt ist, hat nur `doc_root` Einfluss auf die zu öffnende Datei. Der Aufruf einer URL wie `http://my.host/~user/doc.php` hat nicht zum Ergebnis, dass eine Datei im Home-Verzeichnis des Benutzers geöffnet wird, sondern eine Datei namens `~user/doc.php` unterhalb des doc_root (Ja, ein Verzeichnisname, der mit einer Tilde anfängt [`~`]).

Ist das user_dir beispielsweise auf `public_php` gesetzt, wird eine Anfrage wie `http://my.host/~user/doc.php` eine Datei namens `doc.php` im Verzeichnis `public_php` im Heimatverzeichnis des Benutzers öffnen. Wenn das Heimatverzeichnis des Benutzers `/home/user` ist, so ist die ausgeführte Datei `/home/user/public_php/doc.php`.

Die `user_dir`-Expansion erfolgt ohne Berücksichtigung der `doc_root` Einstellung. So können Zugriffe auf die Dokumenten- und Benutzerverzeichnisse separat gesteuert werden.

## Fall 4: PHP-Parser außerhalb des Webverzeichnisbaums

Eine sehr sichere Sache ist es, das PHP-Parser-Binary irgendwo außerhalb des Webverzeichnisbaums zu platzieren, beispielsweise in `/usr/local/bin`. Der einzige Nachteil dieses Verfahrens ist, dass eine Zeile ähnlich der folgenden:

    #!/usr/local/bin/php

als erste Zeile in jeder Datei, die PHP-Tags enthält, stehen muss. Außerdem muss die Datei ausführbar sein. Ansonsten ist sie genauso zu behandeln wie ein beliebiges CGI-Script in Perl oder sh oder anderen gebräuchlichen Scriptsprachen, die den `#!` shell-escape-Mechanismus nutzen, um sich selbst aufzurufen.

Damit PHP bei dieser Konfiguration die `PATH_INFO`- und `PATH_TRANSLATED`-Informationen korrekt auswertet, sollte der PHP-Parser mit der Option --enable-discard-path kompiliert werden.

Zurück | Zum Anfang | Nach vorne
Sicherheit | Nach oben | Apache-Modul