File Inclusions: kleiner Programmierfehler, fatale Wirkung, Teil 1
Beispiele zum Verständnis
Der Code für die folgenden Beispiele ist auf GitHub verfügbar. Der Autor hat das Material unter Mac OS X Mojave, Ubuntu Bionic Beaver und Windows 10 Cmder getestet. Eine detailliertere Beschreibung, was pro Betriebssystem zu beachten ist, steht auf der GitHub-Seite.
Die folgenden Beschreibungen gehen exemplarisch auf Code aus den Bereichen JSP (Version 2.3 mit Apache Tomcat 9.0.21) und PHP (Version 7.3) ein.
Hochfahren der Infrastruktur
Das GitHub-Projekt enthält die in Abbilung 6 gezeigte Infrastruktur. Zum Ausführen ist Docker notwendig. Die Infrastruktur lässt sich mit dem Skript /.start_linux_network.sh
hochfahren. Jeder Server ist auf der einen Seite fest lokal auf 127.0.0.1 verfügbar – und damit nicht außerhalb des Computers – und hat auf der anderen Seite zudem eine interne Docker-Adresse (s. Abb. 7).
Nach der Initialisierung lässt sich nachvollziehen, wie File-Inclusion-Lücken in die Anwendungen kommen.
Breite Front für PHP
PHP bietet die größte bekannte Angriffsfläche. Es reicht folgendes Snippet im Code:
<?php include($_GET['parameter']);?>
Von Haus aus sind zwei Optionen in der Konfigurationsdatei "php.ini" vorhanden, die zwar nicht LFI, aber zumindest RFI über GET-Parameter verhindern, wenn einer von beiden den Wert false
hat:
allow_url_fopen
erlaubt es, auf URL-Teile wie auf normale Dateien zuzugreifen, undallow_url_include
erlaubt das Einbinden entfernter Dateien mit bestimmten Funktionen.
Neben der Anweisung include
existieren noch weitere Methoden, um das Einbinden von Dateien zu ermöglichen, die zur gleichen Lücke führen können:
include_once
,require
,require_once
,eval(file_get_contents(...))
undvirtual
, wenn die Installation von PHP als Apache-Modul erfolgt ist.
Angriff auf JSP
Bei JSP sorgen primär zwei Tags dafür, dass die Sicherheitslücke in den Code gelangt:
c:import
undjsp:include
.
Im Gegensatz zu PHP stehen bei JSP keine Hürden bei der Konfiguration im Weg. Auf der anderen Seite ist der Code komplexer, da Escaping notwendig ist und verschachtelte Tags zum Einsatz kommen müssen.
Zunächst sind Angreifer bei JSP nur innerhalb der Unterverzeichnisse des Webcontainers unterwegs. Gelingt es ihnen jedoch, ein eigens hochgeladenes Skript zur Ausführung zu bringen, ist der Weg aus dem Container frei, und der Angriffsradius erweitert sich.
Die zwei Befehle haben einen unterschiedlichen Einfluss: Im Gegensatz zu jsp:include
erlaubt c:import
zusätzlich das Einbinden externer URLs, was nicht nur einen LFI-Angriff, sondern einen RFI-Angriff ermöglicht.
Ein problematischer Code sieht folgendermaßen aus:
{
<%@ taglib uri =
"http://java.sun.com/jsp/jstl/core"
prefix = "c" %>
<c:import
url = "<%= request.getParameter(\"parameter\")%>"/>
}
beziehungsweise
<jsp:include page="<%= request.getParameter(\"parameter\")%>
Auffällig ist, dass relativ wenig Code ausreicht, um die Lücke auszunutzen – und das mit großer Wirkung.
Exemplarische Angriffsklassen
Folgende Beispiele zeigen das Ausnutzen der unterschiedlichen Angriffsklassen. Über rein lesenden Zugriff lassen sich bestimmte Dateien enthüllen. Diese Form ist unter dem Begriff Directory Traversal einzuordnen.
Potenziell kann PHP auf das gesamte Betriebssystem zugreifen. Zum Auslesen der Benutzerdatei /etc/passwd genügt
http://127.0.0.1:8883/lfi.php?page=/etc/passwd
Und in JSP ist innerhalb des Containers die Webanwendungskonfigurationsdatei "web.xml" folgendermaßen erreichbar:
http://127.0.0.1:8881/webapp/?help=WEB-INF/web.xml