Schützengraben für Admins
Artikel erschienen in Swiss IT Magazine 2005/07
Bei so manchem Administrator dürfte Santy, der Wurm, der rund um das letzte Weihnachtsfest sein Unwesen trieb, noch in guter Erinnerung sein. Der Schädling suchte in mehreren Abwandlungen die Server von Hostern, Firmen und Privatpersonen heim und versuchte, über Sicherheitslücken in der Foren-Software phpBB und einigen anderen Scripts die Server zu kompromittieren. Das Vorgehen war dabei immer gleich: Santy probierte, über unzureichend gefilterte URL-Parameter Code nachzuladen und auszuführen. Ein angreifbarer Code sieht in seiner einfachsten Form so aus:
<?php include($_GET['foo']); ?>
Wenn nun über $_GET['foo'] ein Remote-URL angegeben wird, kann problemlos Code nachgeladen werden, der vom Server ausgeführt wird. Die nötigen Rechte und Scripts vorausgesetzt, kann damit unter Umständen der Server komplett übernommen werden. Gegen derartige Probleme halfen bislang nur zwei Ansätze: Sorgfältiger programmieren und allow_url_fopen in der php.ini abschalten. Während ersteres vor allem auf Shared-Hosting-Servern schwer sicherzustellen ist, macht letzteres etliche Scripts arbeitsunfähig.
Einen effektiven Schutz verspricht dagegen Hardened PHP (www.har dened-php.net), ein Patch, der PHP von Kopf bis Fuss mit einer robusten Schutzrüstung ausstattet und die Funktionalität nur minimal tangiert. Der Patch, der im Laufe von 2004 vom PHP-Entwickler und Sicherheitsspezialisten Stefan Esser entwickelt wurde, erinnert etwas an den grsecurity-Patch für Linux. Denn einerseits wird mit einem verbesserten Speicherschutz die Robustheit des Interpreters verstärkt und andererseits mit zusätzlichen Funktionen der Spielraum der Scripts eingeschränkt.
Der verbesserte Speicherschutz setzt sowohl beim Zend Memory Manager als auch bei den Zend Linked Lists an. Bei beiden werden die allozierten Speicherblöcke mit sogenannten Canaries gegen Speicherüberläufe geschützt. Dies geschieht, indem am Anfang und Ende von jedem mit emalloc() reservierten Speicherbereich 32 Bit lange Zufallszahlen positioniert werden (emalloc() ist ein PHP-interner Wrapper für malloc()). Werden diese überschrieben, wird es von den gehärteten Versionen von efree() und erealloc() erkannt und der Code nicht ausgeführt.
Weiter wurden möglichen Format-String-Attacken das Wasser abgegraben, indem C-Funktionen wie printf() nicht mehr den Modifier %n unterstützen, mit dessen Hilfe es bei ungünstig gestaltetem Code möglich ist, schadhafte Programmroutinen in den Speicher einzuschleusen. Zudem wurden die libc-Funktionen snprintf() und spprintf() durch PHP-eigene Versionen ersetzt.
Anspruchsvoller ist das Stopfen von möglichen Löchern in Scripts, da sich unsaubere Programmierkonstrukte nur schwer identifizieren lassen. Darum bietet Hardened PHP hier nur einen indirekten Schutz, der je nach Script zu wenig oder zu viel sein kann. So wird zum Beispiel das Inkludieren von Quellen, die nach einem URL aussehen, unterbunden, selbst wenn die Variablen überprüft wurden.
Zu den weiteren Schutzmechanismen gehört, dass das Einbinden von auf den Server hochgeladenen Dateien nicht erlaubt ist. Ebenso wird überprüft, ob Strings, welche an Filesystem-Funktionen durchgereicht werden, in ihrer ASCII- und Binär-Form gleich lang sind. Damit sollen Exploits auf Basis von Terminatoren wie %00 (NUL in ASCII) unterbunden werden.
Last but not least implementiert Hardened PHP den momentan einzigen funktionierenden Filter für Variablen. Über vier neue Konfigurationsdirektiven lässt sich steuern, wie viele Request-Variablen entgegengenommen werden dürfen, wie lang ein Request-Variablen-Name sein darf, wie viele Bytes ein Variablen-Wert maximal speichern kann sowie, wie tief Arrays maximal verschachtelt werden dürfen.
Mit diesen vergleichsweise recht einfachen Mitteln lässt sich ein Server vor den übelsten Sicherheitslöchern schützen, ohne dass die Funktionalität nennenswert tangiert wird. Der Administrator wird dabei von einem Logging-Mechanismus unterstützt, der potentielle Angriffe an den Syslog oder das aktuelle SAPI-Log übermittelt. Allerdings verlangt auch ein gehärtetes PHP saubere Programmierung, eine sorgfältige Prüfung von Variablen sowie ein robustes Server-Setup.