Im vorherigen Blockartikel habe ich die Auswirkungen von Meltdown und Spectre aufgezeigt. In diesem Artikel möchte ich Meltdown möglichst einfach und verständlich erläutern, sowie die Angreifbarkeit von Container virtualisierten Umgebungen durch Meltdown an einem konkreten Beispiel aufzeigen. Diese Anleitung soll ebenfalls dabei helfen, dieses Angriffs-Szenario auf eigenen Systemen auszuprobieren.

Meltdown: Funktionsweise – Einfach Erklärt
Im Folgenden wird Meltdown an einem einfachen Beispiel erklärt. Dabei werden zunächst die folgenden vier Schritte durchgeführt:

  1. Speicherbereich allokieren.
  2. Byte aus Kernel-Bereich lesen (unerlaubterweise).
  3. Gelesenes multiplizieren (Geheimnis aus dem Kernel).
  4. Diesen Wert als Index für den allokierten Bereich nehmen (Lesen).

Das Ergebnis wird verworfen, da man nicht aus dem Kernel-Bereich lesen durfte. Jedoch können durch die "out-of-order-execution" die Befehle 3. und 4. ausgeführt werden, bevor die Ergebnisse verworfen werden. Dadurch kann die Information genutzt werden, um einen Teil aus dem allokierten Bereich zu laden. Dadurch befindet sich nun eine Page des allokierten Bereichs im Cache, die direkt abhängig von dem zu lesenden Geheimnis ist. Als nächstes kann nun durch den allokierten Bereich iteriert und jeweils die Zeit für den Zugriff gestoppt werden. Da sich eine Page nun schon im Cache befindet, sollte die Zugriffszeit für diesen wesentlich geringer sein. Der Index dieser Page ist das gelesene Geheimnis.

Dieser Vorgang muss für jedes Byte aus dem Speicher wiederholt werden, um den Speicher auszulesen.

Wer ist Betroffen?

Von der Schwachstelle sind vor allem Intel-Prozessoren betroffen - aber auch der ARM Cortex A75 hat diese Schwachstelle.

Szenario Beschreibung

Ein Szenario für den im Folgenden aufgeführten Exploit wäre das Folgende: 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:

Zeichnung1MeltdownSpectreNgAcenario

Anforderungen

Es wird ein alter Kernel (kleiner 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 "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
An dieser Stelle: Danke an die Autoren dieses POC!

Als letztes wird noch das Docker-Image für den Schadcode benötigt. Das entsprechende Docker file sieht folgendermaßen aus:

FROM ubuntu:18.04
	COPY meltdown-master /meltdown

Das Docker Image kann folgendermaßen gebaut werden:

docker build -t simple-app:V1 .

Exploitation

Für die praktische Durchführung werden die folgenden drei Schritte durchgeführt:

  1. Anzugrufenden Prozess starten (Beinhaltet das Geheimnis, das ausgelesen werden soll)
  2. Anzugrufenden Container starten (Beinhaltet das Geheimnis, das ausgelesen werden soll)
  3. Schadcode ausführen.
    a. Physicher Offset
    b. Speicher-Adresse des Geheimnisses eingeben
    c. Exploitation

Anzugreifenden Prozess starten

Screenshot-from-2019-02-08-15-22-13

Hierzu muss die Secret-Datei innerhalb des geklonten Meltdown-Repositories 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 Geheimnisprogramm kann mit folgendem Befehl gestartet werden:
(Da das Programm eine Libary nutzt, die erweiterten Zugriff benötigt, wird dieser im "privileged Mode" gestartet. Alternativ könnte man die Zugriffe auch manuell setzen. WICHTIG: Der angreifende Code muss nicht(!) privileged gestartet werden. Dieser braucht keine zusätzlichen Rechte.)

docker run -it --privileged simple-app:V1 /bin/bash

Das Ergebnis kann in folgendem Fenster betrachtet werden:

Screenshot-from-2019-02-08-15-22-45

Schadcode ausführen

Zunächst muss ebenfalls 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

In dem Container kann nun das Secret-Programm gestartet werden:

/meltdown/secret

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, wo sich das Geheimnis jeweils 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/
taskset 0x1 ./direct_physical_map.sh

Die Adresse des Geheimnisses wird von den Secret-Programmen ausgegeben. Dadurch kann man dem Meltdown-Exploit diese Daten übergeben und somit das Geheimnis an dieser Stelle direkt auslesen. Dies kann durch folgendes Kommando geschehen:

taskset 0x1 ./../physical_reader 0x1b98156d8 0xffff95ddc0000000

bzw allgemein:

taskset 0x1 ./../physical_reader secret_Addr Phys_Offset

In dem folgenden Bild kann man die Ausführung des Exploits nachvollziehen, sowie die Geheimnisse der angegriffenen Programme erkennen:

Screenshot-from-2019-02-08-15-23-10

Da Meltdown auf physikalischen Effekten aufbaut, könnte es sein, dass es manchmal länger dauert, oder nicht erfolgreich ist. Eine weitere Ausführung sollte dann jedoch funktionieren. Ggf. kann auch das Secret-Programm neugestartet werden. Sollten keine erfolgreichen Ergebnisse erzielt werden, so kann man mithilfe eines Schwachstellenchecks überprüfen, ob man überhaupt angreifbar ist.