PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Local File Inclusion: Einige Beispiele

with 10 comments

Ich habe schon länger keine sicherheitsrelevanten Probleme mehr gepostet, heute schauen wir uns ein paar häufig gemachte und exisierende Fehler an. Schaut euch diesen Code-Schnipsel an:

<?

$url = $_POST['imageUrl'];

$content = file_get_contents($url);

// Put the content of that URL into a database for later use/display

Der Benutzer der Webseite kann also in ein Formular eine URL eintippen, beispielsweise die URL eines Bildes, einer XML-Datei oder einer Webseite. Das Script ruft diese Resource (z.B. ein Avatar Bildchen) ab und speichert es auf der Festplatte oder in einer Datenbank.

Auf einer anderen Seite kann der Benutzer (und vielleicht alle anderen Besucher der Webseite) dieses Bild dann abrufen.

Gibt es hier ein Sicherheitsloch? Ja, gleich mehrere! Was passiert wenn der Benutzer zum Beispiel folgende URLs eingibt:

http://192.168.0.1/monitoring.php

file://admin/config.php

ssh2.exec://root:password@paymentserver:22/sbin/shutdown

Je nachdem welche Wrapper zur Verfügung stehen kann man da ziemlich böse Dinge tun. Man sollte also auf jeden Fall prüfen ob die gegebene URL eine HTTP(S) URL ist die man auch erwartet und die ins Internet führt und nicht auf interne Systeme zugreift. Es sollte auch geprüft werden ob der Inhalt ein gültiges Bild (oder XML…) ist. Eventuell sollte auch geprüft werden ob curl eine bessere Lösung ist denn da stehen die PHP-Wrapper nicht zur Verfügung, wobei die Zugriffe auf interne Server via HTTP oder FTP auch damit möglich sind.

Ein ähnlicher Fall ist der folgende Skriptausschnitt:

<?

$page = $_POST['p'];

require_once $page.'.php';

Normalerweise wird mittels des Parameters p gesteuert welche Seite angezeigt werden soll, beispielsweise das “menu” (menu.php), “home” (home.php) etc. Man darf sich nicht einreden dass ein angehängtes “.php” die Sicherheit erhöht, denn dieses kann durch ein einfaches Null-Byte oder geschickt gewählte Parameter auch umgangen werden.

Ein Angreifer könnte damit jetzt auch seinen Spass haben indem er beispielsweise folgende Werte für p übergibt:

config

http://192.168.1.1/admininterface

../../../../etc/passwd\0
/kunden/web001/htdocs/useruploads/avatars/justuploaded
/tmp/sess_324g234u2z34g
/var/log/apache/access.log

Zweiteres geht natürlich nur wenn allow_url_include aktiviert ist.
Die dritte Zeile zeigt die Null-Byte-Variante (je nachdem ob man via Telnet arbeitet oder via Browser muss man eventuell %00 nehmen statt \0). Das “.php” wird dadurch abgeschnitten.
Die 4. Zeile zeigt den Zugriff auf ein PHP-Script das der Angreifer kurz vorher normal hochgeladen hat, darin könnte beispielsweise ein system() Aufruf sein oder eine Reverse Shell.
Die 5. und 6. Variante laden auch Dateien die der Angreifer vorher mit entsprechenden Referrern, User-Agent-Werten oder Session-Werten gefüllt hat mit PHP-Code: <? system(‘….’); ?>
Die erste Zeile ist relativ unspannend da die Seite weiß bleiben wird, denn in der config.php steht ja PHP Code. Der wird zwar ausgeführt, aber nicht ausgegeben und demnach wird nichts angezeigt. Aber man kommt trotzdem an den Quelltext, mit diesem kleinen Trick:

php://filter/convert.base64-encode/resource=config

Die Ausgabe könnte dann beispielsweise so aussehen:

PD9waHANCiRwd2QgPSAnYWJjMTIzJzs=

und wenn man das wiederum Base64-decodiert hat man den Quelltext der config.php Datei.

Alles hier beschriebene gehört in den großen Bereich Remote File Inclusion und Local File Inclusion, d.h. der Benutzer hat Zugriff und Einfluss auf eingebundene Dateien. An allen Stellen wo ein Benutzer das Laden oder Abrufen von Dateien beeinflussen kann muss höchste Vorsicht geboten sein und alles geprüft werden, am besten gegen Whitelists (letztes Beispiel) oder reguläre Ausdrücke.

Das Aktivieren von open_basedir hilft natürlich auch dabei dass der Angreifer nicht aus dem Projektverzeichnis herauskommt, /etc/passwd wird damit beispielsweise geschützt, aber im Projektverzeichnis oder auf anderen Servern kann der Angreifer nach wie vor tun was er will.

Wie ladet ihr Dateien von fremden Servern herunter die der User bestimmen kann?

Written by Michael Kliewe

März 16th, 2012 at 10:05 am

10 Responses to 'Local File Inclusion: Einige Beispiele'

Subscribe to comments with RSS or TrackBack to 'Local File Inclusion: Einige Beispiele'.

  1. Wie wäre es denn wenn man sich die Domain extrahiert, sich zur IP auflöst und dann prüft das sie nicht lokal ist?

    Wäre das möglich bzw. wirklich sicherer? Und wenn wie? Müsste man ja auch IPv6 mit einbeziehen?

    Florian Heinze

    16 Mrz 12 at 10:30

  2. gibt es wirklich noch seiten, wo solche technik eingesetzt wird? gruselig…

    wolxXx

    16 Mrz 12 at 10:55

  3. Spontan würde ich sagen:

    !is_file(realpath($url = trim($_REQUEST[‘p’]))) ? $url : ”;

    php

    16 Mrz 12 at 11:37

  4. parse_url() und auseinander pflücken :) Formal wie jede andere Validierung auch, oder wer akzeptiert noch “alles” als Email? :D

    KingCrunch

    16 Mrz 12 at 15:10

  5. Von fremden Servern? Avatarchen? Hmmm…Kurz nachdenken…

    cURL. Am besten zuvor kurz ein HEAD absetzen, Content-type aus der Antwort prüfen und dann nach dem Download per GET noch einmal auf die ersten paar Bytes prüfen. Wenn’s kein “#!” oder “ELF” ist, muss man nur noch hoffen, dass ein vorsorglich gestarteter Convert mit GD nicht scheitert (z. B. weil es ein JS für XSS war)…

    Mehr tue ich eigentlich nicht.

    UmbertoKo

    18 Mrz 12 at 22:59

  6. Ich kann nur dringlich empfehlen die SUHOSIN PHP Extension zu installieren, besonders wenn man Fremdsoftware im Einsatz hat, denn damit wird das Nullbyte Problem schon mal erschlagen.

    Sven Jansen

    19 Mrz 12 at 17:40

  7. Hi,
    danke für den Artikel, wieder mal sehr interessant zu lesen, was alles so möglich ist.

    Inspiriert durch diesen Artikel habe ich mal weiter gesucht und bin dabei auf diesen Artikel gestossen
    _http://www.exploit-db.com/papers/15108/

    Dazu mal eine Frage, wenn das in Ordnung ist :)
    Beim Punkt “2. Uploadfunktion:” gibt es folgenden Hinweis:

    “Mittels edjpgcom z.B. kann man Comments in Bilder einfügen.
    So fügen wir unseren PHP Shellcode ein. Nun wird es hochgeladen und man gibt
    den absoluten Pfad des Bildes/der Datei an und schwups, siehe da, der PHP-Code wird ausgeführt. ”

    Was ich hier nicht verstehe, wieso sollte das Bild als PHPCode interpretiert werden ?

    Vielen Dank schon mal
    Sven

    Sven

    23 Mrz 12 at 10:16

  8. @Sven In dem Beispiel wird davon ausgegangen dass in dem anfälligen Script sowas hier steht:

    include($_GET[‘file’]);

    Wenn man diesen Parameter manipuliert kann man jede Datei auf dem Server ausführen. Da eigener Code ausgeführt werden soll muss man diesen auf den Server bekommen. Das geht entweder indem PHP Code in die access.log etc. geschrieben wird, oder indem ein Bild hochgeladen wird mit einem Kommentar, der PHP Code ist.

    Nehmen wir also an es wird ein Avatar Bild hochgeladen das jede Menge kryptischen Code enthält, aber auch den PHP Code:

    GIF89ax………..<?php BÖSER CODE…. ?>

    Diese Datei liegt dann also auf dem Server, und wenn man die dann aufruft:

    http://www.seite.de/index.php?file=../../../../../../../home/fred/domains/fred777.tk/pic.gif

    landet das ja im include() Aufruf und wird wie PHP Code aufgerufen, sprich der Anfang wird einfach ausgegeben, und alles zwischen den PHP Tags wird ausgeführt.

    Michael Kliewe

    24 Mrz 12 at 15:51

  9. […] Script ist, meist passiert das durch schlampige Programmierung. Hier findest du ein paar Beispiele: http://www.phpgangsta.de/local-file-…nige-beispiele wie z.B. unsaubere Programmierung aussehen kann, das ist aber nur ein Bruchteil. […]

  10. @Michael,

    vielen Dank für die Erklärung. Bin ja echt baff, das so PHP Code ausgeführt werden kann…

    sven

    28 Mrz 12 at 11:29

Leave a Reply

You can add images to your comment by clicking here.