Meltdown & Spectre in Container virtualisierten Umgebungen (Teil 3)
16.04.2019
Im ersten Blockartikel habe ich die Auswirkungen von Meltdown und Spectre aufgezeigt. In diesem Artikel möchte ich die Angreifbarkeit von Container virtualisierten Umgebungen durch Spectre aufzeigen. Das Angriffsszenario wird in groben Zügen ähnlich wie das von Meltdown ablaufen: Auch hier kann der Angriff selbst nachgestellt werden.
Spectre: Funktionsweise – Einfach erklärt
Spectre nutzt verschiedene Seiteneffekte (zum Beispiel, dass Werte schon geladen werden) und die spekulative Ausführung von Befehlen durch die CPU, um sensible Daten anderer Programme zu erhalten. Die spekulative Ausführung bezieht sich hierbei auf die Sprungvorhersage der Prozessoren. Der Prozessor nutzt diese Sprungvorhersage, um zu wissen, ob der Sprungbefehl wahrscheinlich ausgeführt wird oder nicht, um dann keine Takte zu verschwenden und gleich die nächsten Befehle laden zu können. Dieser Sprungvorhersage-Algorithmus kann so überbrückt werden, dass der Prozessor denkt, der Sprungbefehl soll ausgeführt werden, dieser aber eigentlich nicht ausgeführt werden darf. Zum Beispiel: Es wird zuerst 100 Mal ein "legaler" Zugriff gemacht, dann denkt der Algorithmus, dass beim 101. Mal ebenfalls der Sprung ausgeführt wird.
Somit kommt es zu einer spekulativen Ausführung des Befehls.
Die Ausführung dieses Befehls kann dann Seiteneffekte verursachen, zum Beispiel das Laden von Werten in den Cache. Diese müssen nun nur noch ausgewertet werden.
Zusammengefasst lässt sich das Vorgehen in die folgenden 3 Punkte aufzeigen:
- Branch Prediction überlisten
- Spekulative Befehlsausführung
==> erzeugt Seiteneffekte
- Seiteneffekte auslesen und Rückschlüsse ziehen
Spectre unterscheidet sich von Meltdown dadurch, dass der andere Prozess Informationen von sich preisgibt und nicht der privilegierte Speicher ausgelesen wird. Des weiteren ist Spectre allgemeiner und beschreibt das Vorgehen vieler Angriffe durch verschiedene Seitenkanäle.
Wer ist Betroffen?
Im Gegensatz zu Meltdown sind von dieser Schwachstelle fast alle Prozessoren betroffen. Für diese Schwachstelle sind zum Beispiel die Prozessoren von AMD, Intel und ARM anfällig.
Sczenario Beschreibung
Ein Szenario für den im Folgenden aufgeführten Exploit wäre: Ein Angreifer hat sich Zugriff auf einen Docker-Container verschafft. Jedoch sind in diesem keine wichtigen Informationen enthalten. Der Angreifer möchte auf die kritischen Daten anderer Services zugreifen. Durch Meltdown ist es ihm möglich, die Applikations-Geheimnisse vom Hostsystem und von anderen Containern in Erfahrung zu bringen. Eine Beschreibung ist in folgendem Bild gegeben:

Anforderungen
Es wird ein alter Kernel (<4.12) für die Durchführung benötigt, da neuere gegen diese Schwachstelle gepatched wurden.
Da wir aus einem Container andere Container (und das Hostsystem) angreifen wollen, wird ebenfalls docker-ce benötigt. Dies kann von der Docker Website installiert werden. https://docs.docker.com/install/
Der benötigte Schadcode für Meltdown (POC) kann von dem git-repository heruntergeladen werden:
git clone https://github.com/IAIK/meltdown.git
Bei dem Spectre-Angriff wird hiervon nur das Secret-Programm benötigt. Der von mir genutzt Spectre Schadcode kann folgendermaßen erhalten werden:
git clone https://github.com/crozone/SpectrePoC.git
Als letztes wird noch das docker-image für den Schadcode benötigt. Das entsprechende Docker-File sieht folgendermaßen aus:
Dockerfile
FROM ubuntu:18.04
COPY meltdown-master /meltdown
COPY SpectrePoC /spectrePoC
Das Docker-Image kann folgendermaßen gebaut werden:
docker build -t simple-app:V1
Exploitation
Für die praktische Durchführung werden analog zu dem Exploitation von Meltdown, die folgenden drei Schritte benötigt:
- Anzugreifenden Prozess Starten (Beinhaltet das Geheimnis, das ausgelesen werden soll)
- Anzugreifenden Container starten (Beinhaltet das Geheimnis, das ausgelesen werden soll)
- Schadcode ausführen.
a. Physischer Offset
b. Speicheradresse des Geheimnisses eingeben
c. Exploitation
Die Schritte werden im Folgenden nochmal kurz aufgeführt. Die meisten Schritte können detailliert im vorherigen Blockpost zu Meltdown eingesehen werden.
Anzugreifenden Prozess starten
Hierzu verwenden wir das gleiche Secret-Programm wie aus dem Meltdown-Angriff. Dieses kann einfach aus dem Meltdown-Repository geklont und ausgeführt werden:
./meltdown-master/secret
Das folgende Bild zeigt die Durchführung. Darin ist die Adresse des Geheimnisses, sowie das Geheimnis selbst (ein einfacher Satz) zu sehen. Es könnte genauso ein privater Schlüssel oder ähnliches sein, der von der Applikation genutzt wird.

Anzugreifenden Container starten
Der Docker-Container mit dem gleichen Geheimnis-Programm kann mit folgendem Befehl gestartet werden. Da das Programm eine Library nutzt, die erweiterten Zugriff benötigt, wird dieser im "privileged mode" gestartet.
WICHTIG: der angreifende Code muss nicht "privileged" gestartet werden – da er keine zusätzlichen Rechte braucht - Spectre kann ohne weitere Rechte ausgeführt werden.
docker run -it --privileged simple-app:V1 /bin/bash
Das Ergebnis kann in folgendem Fenster betrachtet werden.

Schadcode ausführen
Zunächst muss der Docker-Container gestartet werden, der den Schadcode ausführen soll. Dies kann mit folgendem Kommando erreicht werden:
docker run -it simple-app:V1 /bin/bash
Theoretisch könnte man nun mit Meltdown den gesamten physikalischen Speicher auslesen. Da dies aber lange dauern würde, lesen wir direkt an der Stelle, an der sich das Geheimnis befindet. Die Zieladresse setzt sich aus dem physikalischen Offset, und der Adresse des Geheimnisses zusammen. Den physikalischen Offset kann man mit folgender Applikation in Erfahrung bringen:
cd /meltdown/kaslr_offset/
./direct_physical_map.sh

Nun kann man zusammen mit der Adresse, die von dem Secret-Programm ausgegeben wird, die Zieladresse berechnen und an den Spectre-Exploit übergeben. Des Weiteren wird ein Threshold und die Länge des auszulesenden Speichers angegeben.
/spectrePoC/spectre.out 80 ffff913be4b3a540 80
Beziehungsweise allgemein:
spectre.out Thereshould secret_Offset Length
In den folgenden Bildern kann man die Ausführung des Exploits nachvollziehen, sowie die Geheimnisse der angegriffenen Programme erkennen:


Da der Spectre-Angriff auf physikalischen Effekten aufbaut, könnte es sein, dass er nicht beim ersten Mal erfolgreich ist. Weitere Ausführungen sollten dann jedoch funktionieren. Gegebenenfalls kann auch das Secret-Programm neu gestartet werden. Sollten keine erfolgreichen Angriffe erzielt werden, kann man mithilfe eines Schwachstellen-Checks überprüfen, ob man überhaupt angreifbar ist. In der einen Beispielausgabe sind falsch vorhergesagte Ausgaben aufgezeigt. Dabei ist die zweitwahrscheinlichste Ausgabe oft jedoch dann auch die Richtige.