Header-Manipulation-Angriff: Fileupload ohne Schutz

Um sicherzustellen, dass eine Maske zum Hochladen von Dateien auf dem Server nur gewünschte
Dateitypen akzeptiert, empfiehlt z.B. das PHP-Handbuch die Prüfung des Dateitypen, den der
Browser an den Server meldet (http://us3.php.net/manual/de/features.file-upload.php). Die Bezeichnung
des Dateitypen entspricht dem zugeordneten MIME-Type.

Dateitypen und ihre MIME-Types
<br />
Dateityp    MIME-Type<br />
JPEG-Bild    image/jpeg<br />
GIF-Bild    image/gif<br />
PHP-Datei    application/octet-stream<br />

Code zum Prüfen des Dateitypen der hochgeladenen Datei
<br />
<?
php
$file_type 
$_FILES&#91;'userfile'&#93;&#91;'type'&#93;;
if (($file_type != 'image/jpeg') &#038;&#038; ($file_type != 'image/gif')) {
    // Abbruch: Dateityp nicht erlaubt.
}
?><br />

Diese Art der Prüfung ist weit verbreitet und bietet trügerische Sicherheit. Es ist leicht zu zeigen, dass dieser
Schutz nicht genügt und dass er leicht umgangen werden kann. Dabei ist zu beachten, dass der übergebe Dateityp
vom Webbrowser des Nutzers bestimmt wird und im HTTP-Header der Kommunikation zwischen Client und Server gespeichert wird.

Teil des HTTP-Header beim Hochladen einer PHP-Datei
<br />
&
#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;3104147716707<br />
Content-Dispositionform-dataname=&#8220;userfile&#8220;; filename=&#8220;file_upload_crack.php&#8220;<br />
Content-Typeapplication/octet-stream</p>
<
p><?php
echo('Angriff');
?><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;3104147716707&#8211;<br />

Der HTTP-Header kann durch den Angreifer leicht manipuliert werden. Dazu verwendet er beispielsweise einen lokalen
Proxy, der die Daten zwischen Webbrowser und Server abfängt. Aus einer breiten Auswahl geeigneter Proxies wird
hierfür „Paros“ (http://www.parosproxy.org) verwendet. Er erlaubt unter anderem das Abfangen, Manipulieren und Weitersenden der
HTTP-Kommunikation. Die Anwesenheit des Proxies ist für den Server nicht erkennbar. Er geht davon aus, dass sein
Kommunikationspartner der Webbrowser ist.

Ist ein solcher HTTP-Header in Paros abgefangen, so kann er vor dem Absenden beliebig bearbeitet werden. Um
die oben genannte Dateityp-Prüfung zu umgehen, wird der angegebene „Content-Type“ von „application/octet-stream“
nach dem vom Filter zugelassenen JPEG-Bilddatei-Typ „image/jpeg “ geändert. Anschließend wird Paros angewiesen,
diesen HTTP-Header abzusenden.

Teil des manipulierten HTTP-Headers
<br />
&
#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;3104147716707<br />
Content-Dispositionform-dataname=&#8220;userfile&#8220;; filename=&#8220;file_upload_crack.php&#8220;<br />
Content-Typeimage/jpeg</p>
<
p><?php
echo('Angriff');
?><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;3104147716707&#8211;<br />

Eine Prüfung des Dateitypen auf dem Server meldet jetzt eine Datei vom Typ JPEG, die erlaubt ist. Finden keine
zusätzlichen Prüfungen statt, ist der Angriff geglückt und der Angreifer hat Fremdcode auf dem Server eingespielt.

Das könnte dich auch interessieren …

2 Antworten

  1. olly sagt:

    Danke für diese ausführlich Erläuterung. Das ist wirklich sehr verbreitet, ich hatte es auch so. Das ändere ich nun nocheinmal gründlich.

  2. Thomas Schmieder sagt:

    Die Sicherheitslücke beim Upload von Bilddateien mittels PHP-Scripten ist noch viel größer.

    Üblicherweise werden die Bilder nach vermeintlicher Prüfung innerhalb der Document Root (in einem Unterverzeichnis des Accounts) abgelegt und sind dann dort aus auch per HTTP erreichbar. Dateien innerhalb der Document Root werden aber meistens auch vom PHP-Parser geparst, sofern sie z.B. eine passende Endung haben.

    Es ist nun möglich, eine JPG-Datei zu manipulieren und mit der Endung ‚.php‘ (oder einer anderen für den Parser relevanten) auszustatten. Der MIME-Type der Datei bleibt dabei erhalten, denn es handelt sich auch nach der Manipulation immer noch um ein gültiges JPG-Bild. Dieses enthält aber nun PHP-Code.

    Wird die Manipulation derart ausgeführt, dass außerhalb des PHP-Codes und innerhalb im zu interpretie4renden Bereich keine für den Parser ungültigen Zeichen (Bytes) vorkommen, dann würde dieser PHP-Code ausgeführt werden. Wird er genügend geschickt gestaltet, fällt dies am Browser noch nicht einmal auf, denn als letzte Anweisung würde man die Datei selbst per PHP an den Browser ausliefern…

    Es ist also anzuraten, das Parsen von Dateien in Bildverzeichnissen zu unterbinden. Bei der Modulversion von PHP im Apachen geht dies z.B. mit einem Eintrag in der Konfiguration (auch noch in einer .htaccess)

    php_flag engine 0

    .