File Inclusions: kleiner Programmierfehler, fatale Wirkung, Teil 1

Beispiele zum Verständnis

Inhaltsverzeichnis

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.

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).

Zwei Angreifer- und zwei Zielserver sind innerhalb des Netzes konfiguriert (Abb. 6).

Die Log-Ausgabe beim Starten des Skripts zeigt die Adressen an (Abb. 7).

Nach der Initialisierung lässt sich nachvollziehen, wie File-Inclusion-Lücken in die Anwendungen kommen.

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, und
  • allow_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(...)) und
  • virtual, 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 und
  • jsp: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.

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

Die genaue Ausgabe ist erst beim Betrachten des HTML-Quelltexts ersichtlich (Abb. 8).