Ausführen von PHP verhindern...
Jochen
- webserver
0 Felix Riesterer0 Jochen0 Sven Rautenberg0 Felix Riesterer0 Tom
0 Ole0 XaraX- html
Hallo,
zur Absicherung meines CMS möchte ich in Verzeichnissen in denen Dateien hochgeladen werden können die Ausführung von PHP, CGI, PL etc. verhindern. Hierzu habe ich in den entsprechenden Verzeichnissen eine .htaccess-Datei mit folgendem Inhalt abgelegt.
---.htaccess---
Options -ExecCGI
--- EOF ---
Dies funktioniert natürlich auch, nur scheinbar können nun auch PHP-Dateien aus anderen Verzeichnissen nicht mehr auf solch ein Verzeichnis zugreifen. Ein Beispiel hierfür ist das Upload-Verzeichnis für Artikel-Bilder meines CMS. In diesem Verzeichnis befinden sich neben der .htaccess-Datei lediglich .JPG und .GIF Bilder. Die eigentlichen PHP-Scripte die diese Bilder nun verwenden befinden sich in einem übergeordneten Verzeichnis welches natürlich nicht über eine .htaccess-Datei verfügt. Die Ausführung von PHP-Dateien in diesem übergeordneten Verzeichnis ist auch ohne Probleme möglich, nur sobald das Script die Bilder aus dem Upload-Verzeichnis verwenden will ist dies nicht mehr möglich. Das sieht nun so aus, dass in meinem Text keine Bilder mehr aus dem Upload-Verzeichnis angezeigt werden. Im HTML-Code den das PHP-Script erzeugt sind die Bilder jedoch korrekt eingebunden:
<img src="images/image1.gif"">
Nur das Bild wird eben nicht angezeigt. Wenn ich die URL von image1.gif aber direkt im Browser eingebe, funktioniert die Anzeige problemlos.
Was mache ich nun falsch bzw. wie kann man derartige Upload-Verzeichnisse effektiv schützen. Ideal wäre es, wenn man beim Aufruf einer PHP-Datei diese einfach nur als Download bekommt.
Gruß
Jochen
Lieber Jochen,
---.htaccess---
Options -ExecCGI
--- EOF ---
diese Einstellung in einer .htaccess-Datei kenne ich nicht.
Genügt es denn nicht, im upload-Script auf den MIME-Typ zu prüfen, um Dateien, die keine Bilddateien oder HTML-Dateien sind, zu verweigern?
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Es geht ja nicht nur um Bilddateien - ggf. solln auch andere Dateien hochgeladen werden. Zudem will ich Script auch nicht ändern, da der Weg mit .htaccess aus meiner Sicht der effektivere Weg ist.
Gruß
Jochen
Lieber Jochen,
Zudem will ich Script auch nicht ändern, da der Weg mit .htaccess aus meiner Sicht der effektivere Weg ist.
wie Du meinst. Dann finde mal schön in der Apache-Doku die Beschreibung zu Deinem Feature.
Ich an Deiner Stelle hätte mir einfach erlaubt, das Script dahingehend zu modifizieren, dass es anhand des MIME-Typs unerlaubte Dateien erst garnicht zulässt.
Eine andere Möglichkeit wäre, mit mod_rewrite alle Dateien mit der Endung .php aus diesem Verzeichnis "umzuleiten", um ein Script mit entsprechender Meldung auszuführen... Wäre das vielleicht eine Lösung?
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Hello,
Es geht ja nicht nur um Bilddateien - ggf. solln auch andere Dateien hochgeladen werden. Zudem will ich Script auch nicht ändern, da der Weg mit .htaccess aus meiner Sicht der effektivere Weg ist.
Ich empfinde Deine Idee durchaus als Bereicherung meiner Ideenkiste.
Trotzdem würde ich zusätzlich im Script auf die _erlaubten_ Dateitypen prüfen und alle anderen rigoros isolieren oder sogar sofort löschen.
Deine Frage kann ich im Moment noch nicht beantworten, bin mir aber auch nicht sicher, ob das
Options -ExexCGI
ausreichen würde. siehe http://httpd.apache.org/docs/2.0/mod/core.html#options
Läuft denn PHP bei Dir als CGI oder als Modul?
Die Frage bleibt somit für mich interessant, da ich bisher keine Idee habe, wie man das Gewünschte bei der Modulversion (einfach) erreichen könnte.
Außerdem müsste man auch sicherstellen, dass der User kein exec(), include() usw. mit Files aus dem Verzeichnis benutzen darf.
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Moin!
Genügt es denn nicht, im upload-Script auf den MIME-Typ zu prüfen, um Dateien, die keine Bilddateien oder HTML-Dateien sind, zu verweigern?
Der Mime-Typ ist eine vom Client gelieferte Information und daher nicht vertrauenswürdig.
- Sven Rautenberg
Lieber Sven,
Der Mime-Typ ist eine vom Client gelieferte Information und daher nicht vertrauenswürdig.
das habe ich noch nicht gewusst. Danke für die Info!
Muss nicht der Server diese Datei mit irgendeinem MIME-Typ verwalten? Ich überlege, inwieweit ich eine hochgeladene Datei darauf prüfen kann, ob sie "erlaubt" sein soll, oder nicht...
Wäre denn mit is_executable() oder filetype() eine verlässliche Prüfung zu realisieren?
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Hello Felix,
war das eben "zu früh gebrüllt Löwe"?
Die Idee von Jochen finde ich nämlich gar nicht schlecht.
Und da sollte man ihn nicht einfach so angehen, sondern besser helfen bei der Feststellung, ob es eine gute ist... :-)
Der Mime-Typ ist eine vom Client gelieferte Information und daher nicht vertrauenswürdig.
das habe ich noch nicht gewusst. Danke für die Info!Muss nicht der Server diese Datei mit irgendeinem MIME-Typ verwalten? Ich überlege, inwieweit ich eine hochgeladene Datei darauf prüfen kann, ob sie "erlaubt" sein soll, oder nicht...
Eben darum geht es Jochen! Er meinte, eine andere effektive Lösung gefunden zu haben. Ich meine, dass seine Idee Lücken hat.
Wäre denn mit is_executable()
Das prüft lediglich, ob das Execute-Flag (Die Rechte für den User oder die Gruppe) im Dateisystem gesetzt ist. Es ist der Funktion egal, ob der Inhalt der Datei tatsächlich ausführbar ist. Für PHP gilt das ohnehin nicht, da die Ausführung nicht in der Shell des OS, sondern im Runtime von PHP durchgeführt wird.
oder filetype() eine verlässliche Prüfung zu realisieren?
Da hättest Du nun mal die Beschreibung lesen sollen. Der Speicherverwaltungstyp der Datei hat nichts mit ihrer Ausführung zu tun.
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Moin!
Muss nicht der Server diese Datei mit irgendeinem MIME-Typ verwalten?
Nein. Unix beispielsweise kennt erst einmal nur Dateien. "Alles ist Datei" - selbst Festplattenpartitionen, serielle Schnittstellen oder TCP-Sockets.
Mime-Typen sind ein über dieses Grundgerüst drübergelegter Layer, der jeder Datei einen Mime-Typ, und dann jedem Mime-Typ eine typische Verarbeitungsform zuordnet. Wobei die Zuordnung eines Mime-Typs sehr häufig auf der Dateiendung basiert, dies aber nicht so sein muß - man kann den Mime-Typ auch unabhängig in Dateimetadaten speichern, dazu muß das Dateisystem sowas aber unterstützen.
In der realen Welt werden Mime-Typen tatsächlich nur für den Datenaustausch zwischen Systemen verwendet, die internen Betriebssystemvorgänge interessieren sich dafür herzlich wenig. Es wird beispielsweise nicht verhindert, dass ich ein JPG mit einem Texteditor öffne. Wobei: Das Verhindern kann ja auch gegen die Userinteressen laufen, manchmal will man genau das ja tun.
Ich überlege, inwieweit ich eine hochgeladene Datei darauf prüfen kann, ob sie "erlaubt" sein soll, oder nicht...
Diese Prüfung ist schwierig, und erfordert zuallererst mal eine Festlegung, welche Dateien denn als "erlaubt" gelten sollen.
Die Prüfung wird sich dann daran machen, das erlaubte Dateiformat in der Datei zu finden, und bei Abweichungen die Erlaubnis zu verweigern. Was darauf hinausläuft, dass man alle erlaubten Dateiformate kennen muß.
PHP hat mit getimagesize() eine Funktion, die schon sehr viele Bilddateiformate kennt und daraus die Größeninformation gewinnen kann. Falsches Format = keine Bildinformation = vermutlich kein Bild = keine Erlaubnis.
Bei Word-Dateien wird's schon schwieriger: Kennst du alle möglichen Dateiformate von Word?
Also wird man normalerweise einfach "alle Binärdateien" zulassen und durch Programmierung versuchen zu verhindern, dass man auf dem Server mit den Dateien außer Hoch- und Runterladen was anderes machen kann - "als Programm ausführen" beispielsweise wäre extrem böse.
Dasselbe gilt für "Textdateien", die im Prinzip nur eine unbedeutende Sonderform von "Binärdatei" sind. Zu verhindern, dass jemand eine Textdatei mit PHP-Code hochlädt und den Code dann (anstatt eines Downloads) ausführt, ist sehr wichtig.
Wäre denn mit is_executable() oder filetype() eine verlässliche Prüfung zu realisieren?
is_executable() liefert dir, ob die Datei im Unix-Dateisystem das X-Flag gesetzt hat. Ob Unix die Datei ausführen kann, ist damit nicht gesagt - auch fehlerhafte Programme haben das Flag gesetzt, und ebenso alle Dateien, die einem globalen CHMOD 777 zum Opfer fallen, weil sonst FTP oder Dateizugriff nicht richtig geht.
filetype() liefert für alle regulären Dateien das Ergebnis "file". Unterscheidet also auch nach nichts relevantem.
Hat Tom aber schon beides erwähnt.
Im Prinzip kann man sagen: Ob eine Datei erlaubt sein soll, oder nicht, muß man durch Validierung der Eingabe feststellen, genau so, wie man es bei Formularfeldern auch tun muß. Das Problem ist dabei nur, dass Formularfelder wesentlich einfachere Formate haben, Dateien hingegen ziemlich komplex sein können.
Und wenn man die vom User übermittelten Daten nicht komplett verifizieren kann, dann muß man eben dafür sorgen, dass sie keinen Schaden anrichten können, eingebauter Code also nie zur Ausführung gelangt. Das gilt für Dateien (hier: hochgeladene PHP-Skripte) genauso, wie für Formularfelder (Stichwort: SQL-Injection - das ist auch ausführbarer Code, nur kürzer und in einem Formularfeld).
Die Prinzipien sind, egal ob Datei oder Formularfeld, identisch.
- Sven Rautenberg
Hello,
Und wenn man die vom User übermittelten Daten nicht komplett verifizieren kann, dann muß man eben dafür sorgen, dass sie keinen Schaden anrichten können, eingebauter Code also nie zur Ausführung gelangt. Das gilt für Dateien (hier: hochgeladene PHP-Skripte) genauso, wie für Formularfelder (Stichwort: SQL-Injection - das ist auch ausführbarer Code, nur kürzer und in einem Formularfeld).
Das erinnert mich daran, dass es für den Schaden gar nicht immer wichtig ist, ob der Code nun auf dem Server oder auf dem Client ausgeführt wird. Es gibt da ja diese nette Hintertür in der Rendering-Maschine für JPGs bei Windows. Auf dem Unix-Server wird eine infizierte JPG-Datei vermutlich keinen Schaden anrichten, wenn sie dann aber von einem Client angefordert wird, der dieses Rotte OS drauf hat, dann ist es zu spät.
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Hello,
Das erinnert mich daran, dass es für den Schaden gar nicht immer wichtig ist, ob der Code nun auf dem Server oder auf dem Client ausgeführt wird. Es gibt da ja diese nette Hintertür in der Rendering-Maschine für JPGs bei Windows. Auf dem Unix-Server wird eine infizierte JPG-Datei vermutlich keinen Schaden anrichten, wenn sie dann aber von einem Client angefordert wird, der dieses Rotte OS drauf hat, dann ist es zu spät.
*Ups* zu früh geklickt:
Ich wollte darauf hinweisen, dass man auch gegen diese Form des Missbrauchs auf dem Server nach dem Hochladen etwas tun kann, und zusätzlich zur MIME-Type-Prüfung auch noch eine Virenprüfung nachschalten könnte. Leider kenne ich im Moment keine, die man so einfach in PHP einbauen kann.
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Hello,
Der Mime-Typ ist eine vom Client gelieferte Information und daher nicht vertrauenswürdig.
...deshalb sollte man ihn ja auch auf dem Server "auswürfeln" lassen. sofern das möglich ist.
Der Magic MIME File ist leider nicht immer vorhanden oder es gibt (je nach OS) gar keine Möglichkeit, den Typ festzustellen.
Also mit getimagesize() nach Bild gucken
wenn es keines ist, z.B. mit if(strpos($filedata,chr(0)) !== false) die Executables aussortieren,
...
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
hi
Prüfe doch einfach nach (vor geht nicht zuverlässig) dem Upload die Dateiendung und lösche die Datei gegebenenfals.
so long
Ole
(8-)>
Hallo,
<img src="images/image1.gif"">
-----------------------------^^
könnte es sein, daß es nur dieser Fehler ist? Anderes schlösse sich nach Deinen Informationen aus, da Serverrestriktionen PHP und das Dateisystem herzlich wenig interessieren.
Gruß aus Berlin!
eddi