Zurück zur Übersicht


Geschrieben am 29.6.2010 um 20:23 Uhr von Klopfer in der Kategorie Tipps

Vorsicht vor doppelten Dateiendungen

Online-Anwendungen abzusichern, wird immer aufwändiger, was natürlich auch der Entwicklung zum Mitmach-Web geschuldet ist. So muss man grundsätzlich jeder Nutzereingabe misstrauen und daran arbeiten, sie von Schadcode zu befreien, um beispielsweise Cross-Site-Scripting-Attacken zu entschärfen.
Was vielen nicht bewusst ist: Auch bei Dateiuploads muss man besondere Vorsicht walten lassen.

Eine Angriffsmöglichkeit basiert auf einer Eigenart des Apache-2-Webservers. Dieser interpretiert nämlich mehrfache Dateiendungen. Um das zu verdeutlichen, ein kleines Beispiel: Nehmen wir an, der Webserver ist so konfiguriert, dass .pl-Dateien an den Perl-Interpreter geschickt werden, .php-Dateien an den PHP-Interpreter. Eine Datei beispiel.php.pl würde vom Apache also zu beiden Interpretern geschickt werden (was natürlich zumindest für einen Interpreter keinen Sinn ergeben würde).

Diese Eigenart führt zu einer Schwachstelle bei Datei-Uploads, wie viele Seiten ihren Mitgliedern per Webinterface ermöglichen, etwa um Profilbilder oder eigene Avatare zu realisieren. Viele Skripte prüfen nur oberflächlich, ob die Dateiendung auf eine Bilddatei hinweist (also zumeist .jpg, .jpeg, .png und .gif). So hat ein Angreifer die Möglichkeit, eine Datei der Form badscript.php.jpg hochzuladen, die er dann (sofern er die Adresse des Upload-Verzeichnisses kennt) über einen Browser aufrufen und mit den Rechten des Webservers als normales Skript ausführen kann.

Welche Gegenmaßnahmen muss man ergreifen?
Grundsätzlich ist zu empfehlen, den Dateinamen zu verändern und die Datei auf ihren Typ zu überprüfen. Die Überprüfung des Dateityps ist in PHP sehr einfach. Die Funktion getimagesize() liefert ein Array zurück, in dem an dritter Stelle die Art der Bilddatei angegeben ist (1 = GIF; 2 = JPEG, 3 = PNG usw.). Steht dort der Wert 0 oder ein Wert, der nicht zu den erwarteten Bilddateien passt, sollte das Upload-Skript die Datei löschen und eine Fehlermeldung ausgeben.
Wenn man so die Art der Bilddatei herausgefunden hat, kann man diese Information für den neuen Dateinamen verwenden (um etwa gültige Bilddateien, die mit falscher Dateiendung hochgeladen wurden, korrekt zu benennen) und selbst versehentliche doppelte Endungen zu tilgen. Außerdem bietet sich an, die neuen Dateinamen gleich so zu wählen, dass später hochgeladene Dateien keinesfalls den gleichen Namen bekommen können, also beispielsweise über Upload-Datum und -Zeit.

Wer also solche Upload-Skripte geschrieben hat, ohne bewusst auf diese Schwachstelle zu achten, sollte lieber jetzt noch einmal seinen Quellcode durchgehen.

5 Kommentar(e)


Geschrieben am 29.6.2010 um 22:29 Uhr
Lubin

Danke noch mal für den Hinweis -- das habe ich auch erst letztens schockier bemerkt.

Man kann den Apache HTTPd aber auch direkt so konfigurieren, dass er wirklich nur die Endung der Datei beachtet, allerdings setzt das in der Regel natürlich Zugriff auf die httpd.conf voraus. Das Beste wäre es andernfalls, sich an den Hoster zu wenden. Die sind in der Regel auch nicht so an unsicheren Webservern interessiert.

Alternativ, wenn man genügend Rechte in der .htaccess hat, geht auch:

RemoveType .php
<FilesMatch .php$>
SetHandler application/x-httpd-php
</FilesMatch>

Wobei man natürlich für weitere, möglicherweise für PHP zugelassene Endungen (.php3, .php4, .php5, .phtm, .phtml u. ä.) noch entsprechende RemoveType-Anweisungen ergänzen muss.

Der Tipp mit getimagesize() ist übrigens aber falsch! Die Funktion mag zwar prüfen, ob es sich um ein gültiges Bild handelt (wie zuverlässig das ist, weiß ich jetzt nicht), aber das ist KEINE Garantie, dass da kein PHP-Code drin steckt!

Alle Bildformate unterstützen Kommentarfelder und in diesen kann man u. U. durchaus PHP-Code unterbringen. Und was tut PHP, wenn sein PHP-Code von irgendwelchem nicht-PHP-Zeug umgeben ist? Richtig, es schickt das Zeug an den Browser und führt den Code dennoch aus. Damit hat man also überhaupt nichts gewonnen.

Geschrieben am 29.6.2010 um 22:33 Uhr
Lubin

Ups, da hab ich nicht gut genug gelesen. Dein Tipp mit getimagesize() war ja ein ganz anderer als ich verstanden habe. Tut mir Leid.

Aber erwähnt haben wollt ichs' mal. :P

Geschrieben am 30.8.2010 um 21:12 Uhr
Texasranger

Reicht nicht ein einfaches strpos() im phpscript um zu prüfen ob die endung .php im dateinamen versteckt ist? Denn wenn man andere Dateien als Upload zulässt zum beispiel .zip reicht dein getimagesize() nicht mehr aus. Oder täusch ich mich da?

Geschrieben am 28.3.2012 um 2:13 Uhr
Gast

Es heißt nicht aufwändiger. Was hat das mit wänden zu tun? Gleich im ersten Satz also wirklich ;)

Geschrieben am 11.10.2012 um 22:29 Uhr
Gast (Website)

w ddfb


Eigenen Kommentar schreiben

Kommentar:
Smilies und Codes
Name: (darf nicht leer sein)
E-Mail: (nicht öffentlich sichtbar)
Website:
Spamschutzfrage: Wie nennt man ein weibliches Hausschwein?
Username: Passwort: