Grundsicherung für PHP-Software

Seite 2: PHP via CGI

Inhaltsverzeichnis

Der von den meisten Hostern eingesetzte CGI-Ansatz ist flexibel und richtig konfiguriert auch recht sicher. Dabei laufen PHP-Anwendungen über den klassischen CGI-Mechanismus als eigener Prozess. Damit die Skripte dabei dann nicht mit vollen Server-Rechten sondern mit User-Rechten laufen, setzen die Provider die Apache-Module mod_suexec oder mod_suphp ein. Das schützt nicht nur den Server selbst vor den Konsequenzen von Einbrüchen, sondern auch die anderen Servernutzer.

Weiterhin hat der Web-User bei einer CGI-Konfiguration nahezu unbegrenzte Einflussmöglichkeiten auf die PHP-Optionen. Denn der PHP-Interpreter verwendet im CGI-Modus bevorzugt eine php.ini-Datei, die im selben Verzeichnis wie das aufgerufene PHP-Skript liegt.

Eine php.ini gilt anders als .htaccess-Dateien allerdings nicht für Unterverzeichnisse. Daher gehört in jedes Verzeichnis mit PHP-Skripten, die sich direkt aufrufen lassen, eine eigene php.ini-Datei. Bei reinen Include-Verzeichnissen – wie etwa dem wp-content-Ordner des Blog-Systemes Wordpress – ist das nicht nötig. Im Zweifel sollte man jedoch lieber auf Nummer sicher gehen und in jedes Verzeichnis eine php.ini kopieren. Wenn manuelles Kopieren zu aufwendig ist, kann das kleine Perlskript ftp_spread.pl behilflich sein. Es kopiert eine beliebige Datei in jedes Unterverzeichnis eines anzugebenden FTP-Pfades.

Bevor man sich an die Arbeit macht, passende php.ini-Dateien zu erstellen, hier ein kurzer Überblick über die wichtigsten Sicherheitsoptionen von PHP:

  • allow_url_fopen (empfohlen: off) steuert, ob Dateizugriffe auch auf externe URLs verweisen dürfen oder nicht. Verbietet man dies, fällt es einem Angreifer schwerer, Schadprogramme aus dem Internet nachzuladen. Seit PHP 5.2.0 regelt allow_url_include das Verhalten separat für die Befehle include() und require().
  • display_errors (empfohlen: off) schaltet die Anzeige von PHP-Fehlermeldungen ein oder aus. Was fürs Debugging hilfreich ist, kann andererseits auch Angreifern Aufschluss über Anwendungsinterna geben, die für weitere Attacken hilfreich sind.
  • disable_functions spezifiziert eine Liste von gesperrten PHP-Funktionen. Insbesondere PHP-Anwendungen, die unter Sicherheitsapekten entwickelt wurden, machen einen großen Bogen um potenziell gefährliche Funktionen wie exec(), sodass ihr Fehlen ihnen häufig keine Probleme bereitet -- vielen im Umlauf befindlichen Exploits aber sehr wohl.
  • open_basedir (empfohlen: Web-Home) limitiert die Dateioperationen von PHP auf das angegebene Verzeichnis und darin enthaltene Unterverzeichnisse. Es ist möglich, mehrere Verzeichnisse mit einem Doppelpunkt getrennt anzugeben. Wichtig ist, Pfadangaben mit einem Slash zu beenden, da sie andernfalls auch alle Verzeichnisse einschließen, die mit dem angegebenen Namen beginnen.
  • register_globals (empfohlen: off) steuert, ob Skripte Parameter aus der URL oder den POST-Daten als globale Variablen übergeben bekommen oder nicht. Viele Schwachstellen in PHP-Anwendungen lassen sich nur ausnutzen, wenn dies der Fall ist.
  • safe_mode (empfohlen: on) gibt an, ob PHP in einem speziellen abgesicherten Modus laufen soll oder nicht. Er hat weitreichende Auswirkungen, beispielsweise findet bei Dateioperationen ein zusätzlicher UID-Check statt und der Zugriff auf Umgebungsvariablen ist eingeschränkt. PHP6 wird ihn nicht mehr enthalten, weil die Entwickler der Ansicht sind, dass seine Funktionen nicht im Aufgabenbereich einer Skriptsprache liegen. Auf der PHP-Seite ist er umfassend dokumentiert [3].
  • sql.safe_mode regelt eine Sonderbehandlung von Anmeldungen an Datenbankservern. In diesem Modus verwenden die PHP-Funktionen zur Datenbankanmeldung ausschließlich den Namen des System-Users, dem das Skript gehört. Da in Shared-Webhosting-Umgebungen der Name des Datenbanknutzers fast nie mit dem es System-Users übereinstimmt, kommt dort diese Option nur äußerst selten in Frage.

Eine besonders abgedichtete php.ini hat damit den folgenden Inhalt:

[PHP]
register_globals = off
allow_url_fopen = off
safe_mode = on
open_basedir = <Pfadname des Webverzeichnisses>
disable_functions = exec,system,passthru,shell_exec,popen,escapeshellcmd,proc_open,proc_nice,ini_restore
display_errors = off

Einige dieser Optionen sind noch anzupassen. Für open_basedir ist der Pfad zum Web-Root einzutragen, wie er beispielsweise in der PHP-Variablen DOCUMENT_ROOT der Ausgabe von phpinfo() zu lesen ist. Sind mehrere Applikationen in verschiedenen Unterverzeichnissen mit eigenen php.ini-Dateien installiert, ist es empfehlenswert, jeweils den Basispfad der zu schützenden Web-Anwendung einzutragen.