Mittlerweile hat es sich ja bei den meisten PHP Entwicklern herumgesprochen dass Sie mehr Wert auf die Sicherheit ihrer Skripte legen müssen oder sollten.
Daher ist es immer wieder erstaunlich wie viele Skripte tatsächlich noch anfällig gegen die einfachsten Angriffe sind.
Heute möchte ich eine Simple Angriffsmethode erläutern, Sie beruht darauf dass ein Skript gegeben ist welches eine Date includiert.
In der Url sieht dies Beispielsweise so aus:
http://www.irgendwas.net/page.php?page=Home.txt
Nun wie sieht es in dem php Skript page aus? Im detail weiß man dass nie ganz genau. Aber der grobe Ansatz schaut folgendermaßen aus:
/**
Auszug aus einem anfälligen PHP Skript!
Zu tutorial!!
**/
if(isset($_GET['page'])) {
print $_GET['page'];
$fp = fopen($_GET['page'], "r");
$HTML = fread($fp, filesize($_GET['page']));
fclose($fp);
print $HTML;
}
?>
So oder ähnlich sind diese Skripte aufgebaut. Es ist auch denkbar dass das ganze nur über einen include Befehl eingebunden wird. Das stört uns hier aber nicht unbedingt.
Als erstes muss man herausfinden ob ein Skript überhaupt anfällig für diesen Angriff ist.
Am einfachsten geht dass wenn man aus der Variablen ein Array macht. Somit müsste sich ein Fehler ergeben da dass Skript so nicht mehr auf die Variable zugreifen kann.
URL: http://www.irgendwas.net/page.php?page[]=Home.txt
Warning: fopen() expects parameter 1 to be string, array given in /var/www/irgendwas/page.php on line 8
Warning: filesize() [function.filesize]: stat failed for Array in /var/www/irgendwas/page.php on line 9
Warning: fread(): supplied argument is not a valid stream resource in /var/www/irgendwas/page.php on line 9
Warning: fclose(): supplied argument is not a valid stream resource in /var/www/irgendwas/page.php on line 10
Hier bekommt man mehrere Fehlermeldungen. Es kann auch sein dass keine Fehlermeldung kommt. Ganz wie der Server konfiguriert wurde. Aber im besten oder im schlechtesten sieht man es wie oben. Zumindest sehe ich nun das Verzeichniss und wie tief es verschachtelt ist!
Wenn ich jetzt zum Beispiel die Apache Konfiguration auslesen möchte dann ändere ich die URL wie folgt ab:
?page=../../../../etc/apache2/apache2.conf
Wenn man nun die Seite anfordert sieht man die gesammte Konfiguration des Servers! Aus diesen Informationen kann man sehr viel herauslesen.
Oder geschützte Verzeichnisse. Denn das Skript kann den Inhalt des geschützten Verzeichnisses auslesen. Solange das Verzeichniss mittels .htaccess gesichert wurde.
Hier ein Beispiel:
/var/www/irgendwas/geheim/ Geschütztes Verzeichniss
Der Zugriff auf die .htaccess sieht dann folgendermaßen aus:
http://www.irgendwas.net/page.php?page=geheim/.htaccess
So nun habe ich die gesamte .htaccess auf dem Monitor und kann damit weiter in das System
eindringe.
Somit ist dass Prinzip dieser Angriffsmethode klar. Sie beruht auf eine schlechte (unsichere) Programmierung. Doch wie kann man so ein PHP Skript sicher gestalten?
Zum einen ist es nicht empfehlenswert einfach Daten aus der URL zur includierung zu Benutzen. Dass ist immer anfällig und hunderprozentig sicher ist dass nicht!
Ich würde empfehlen die Daten, also die Textdateien in einem Array aufzubewahren.
Dieses Array kann man ja auch automatisch erzeugen lassen. Wichtig ist dass in diesem Array nur txt Dateien stehen!
Dann wollen wir dass in der url eine Zahl übergeben wird. Diese Zahl zeigt auf den Index des Arrays und ermöglicht so den Zugriff auf die Datei!!
Also bsp so:
$txt_Dateien= array('Hallo.txt', 'Home.txt' , 'Mail.txt' );
if(isset($_GET['page'])) { //Abfrage ob die Variable übergeben wurde
settype($_GET['page'], "integer"); //Typenkonvertierung von String in integer, nur Zahlen!!
if($_GET['page'] < count($txt_Dateien) && $_GET['page'] > -1) { //Überprüfen ob die Zahl auch kleiner als der index von unserem Array ist!! Ansonsten gäbe es eine Fehlermeldung!
$fp = fopen($txt_Dateien[$_GET['page']], "r");
$HTML = fread($fp, filesize($txt_Dateien[$_GET['page']]));
fclose($fp);
print $HTML;
}
}
?>
Das Skript oben ist nicht die Best Practice Lösung ein sicheres Skript zu erstellen aber ein guter Ansatz. Es sollte immer vermieden werden Dateien aus dem System per benutzereingabe einzubinden.
Aber wenns dennoch sein muss stellt dass ein guter Weg dar es einzubinden. Dabei wird jede Benutzereingabe erst in einen integer also eine Zahl konvertiert und danach wird überprüft ob die Zahl kleiner als das Ergebniss von "count(array)" ist.Kleiner Deshalb da count mit 1 anfängt zu Zählen. Aber das array selbst beginnt mit 0 deshalb immer kleiner als dass Array.
Das wäre noch nicht sicher denn ich könnte eine Fehlermeldung provozuieren in dem ich eine negative Zahl eingebe. Also muss die Zahl größer als -1 sein!
Somit sind dass alle Zahlen von 0 bis 2 in diesem Beispiel!
Ich hoffe dass kleine Tutorial hat geholfen ein paar PHP Skripte sicherer zu machen und das Verständnis für diese Problematik in der PHP Entwicklung zu stärken!
Kommentare