Meltdown – Alptraum der CPU-Entwickler und Administratoren
12. Januar 2018„Meltdown“ macht sich konzeptionelle Schwachstellen im CPU-Design zu Nutze. Um die Performance zu erhöhen, rechnen nicht genutzte CPU-Ressourcen („freie“ Register) schon einmal mit den Daten, die vermutlich bald benötigt werden. Das Vorgehen weist allerdings unerwünschte Seiteneffekte auf. Denn mit der „out-of-order execution“ werden die bereits angesprochenen Daten (die vorsorglich in den Cache geladen wurden) ausgelesen. Selbst wenn die korrespondierenden Speicheradressen eigentlich vor dem Zugriff (durch den „Kernel-Modus“) geschützt sein sollten, gelingt es Daten direkt aus den Registern und dem Cache Abfließen zu lassen. Besonders gefährdet sind dabei virtuelle Systeme von Cloud-Providern. Schließlich „laufen“ auf einem Server unter Umständen VMs von dutzenden unterschiedlichen Mietern – ein perfektes Ziel für Hacker.
Für eine effiziente und funktionierende IT-Systemsicherheit sind unterschiedliche Punkte zu beachten. Auf den „höheren“ Schichten (etwa dem Betriebssystem-Level oder der Anwendungsschicht) tauchen immer wieder Sicherheitslücken in Softwarekomponenten auf, die mit entsprechenden Hotfixes und Patches wieder „gestopft“ werden müssen. Auch die Benutzer selbst sorgen immer wieder dafür, dass Hacker und deren Schadsoftware Dateien oder sensible Informationen „entwenden“ können – etwa durch allzu bereitwilliges Anklicken von E-Mail-Anhängen.
Auf den unteren Schichten des OSI-Modells (etwa der Transport- oder Vermittlungsschicht) sorgen bestimmte Mechanismen dafür, dass Datenpakete im Netzwerk auch genau an dem Ziel ankommen, für das sie bestimmt sind. Je weiter man sich von den Anwendungen und Betriebssystemen „nach unten“ bewegt, desto schwieriger wird es Fehler zu erkennen und entsprechende Gegenmaßnahmen einzuleiten. Das gilt für die Systembetreuer als auch für die Entwickler und Hersteller von Hardware, Firmware und Software gleichermaßen. Denn falls sich eine ausnutzbare Sicherheitslücke in der Gerätefirmware befindet, wird es für die darüber liegenden Sicherheitsmechanismen (etwa eine Firewall oder eine Endpoint-Virenschutz) schwer oder unmöglich, diesen zu erkennen.
Besonders im Bereich der IT-Kernkomponenten (CPU, RAM, Mainboard, Speichermedien) müssen sich die IT-Sicherheitsbeauftragen darauf verlassen können, dass diese Systeme „sicher“ sind. Damit dies der Fall ist, müssen beispielsweise bestimmte Dateien in den unterschiedlichen Speicherbereichen voneinander zu isoliert werden. Sprich wenn mehrere Anwendungen, virtuelle Maschinen oder Benutzer auf einem Server arbeiten, dürfen die Dateien von Benutzer-01 (oder VM-01 oder Anwendung-01) nicht auch für Benutzer-02 zur Verfügung stehen. Diese Abgrenzung der jeweiligen Speichern Bereiche wird als „memory isolation“ bezeichnet. Dazu zählen etwa Hauptprozessor-Caches (meist Level 1 bis Level 3), Hauptspeicher (oftmals DRAM) sowie die Massenspeichermedien (etwa mechanische Festplatten oder Solid State Drives). Nun hat sich allerdings herausgestellt, dass die Hardware-gestützte Implementierung einer kompletten „memory isolation“ auf sehr vielen CPUs fehlerhaft ausgeführt ist.
Probleme beginnen bei der CPU
Um die Probleme bei der fehlerhaften Implementierung zu verstehen, ist es zunächst wichtig, sich über einige Punkte in Bezug auf die Ansteuerung von CPUs durch das Betriebssystem vertraut zu machen: Nur bestimmten Teiles des Betriebssystems (meist der namensgebende „Kernel“) ist es erlaubt, direkt auf die Hardware zuzugreifen. Die restlichen Softwarekomponenten, Programmen und Benutzerkonten können somit nicht direkt auf die Hardware einwirken. Damit die Programme die Illusion eines direkten Speicherzugriffs erhalten, setzen moderne Betriebssysteme etwa Funktionen wie einen HAL (Hardware Abstraction Layer) sowie entsprechende Speichervirtualisierungen ein. Auf diese Weise „gaukelt“ das OS den jeweiligen Programmen vor, sie würden Zugriff auf den Hauptspeicher (oder den CPU-Cache oder das CPU-Register erhalten).
Um eine „saubere“ Trennung der jeweiligen Daten sicherzustellen, arbeiten CPUs in zwei (oder mehreren) unterschiedlichen Modi. Hier sind zum einen der „Kernel-Modus“ und zum anderen der „User-Modus“ zu nennen. Bestimmte Prozessor Architekturen (etwa Intel x86) verfügen über weitere Modi. Diese werden beispielsweise als Ring0, Ring1, Ring2 und Ring3 bezeichnet. Bei diesem Beispiel entspricht „Ring0“ dem „Kernel-Modus“ und Ring3 wird als User-Modus verwendet. Ring1 und Ring2 werden dabei nicht unbedingt vorausgesetzt – um die Kompatibilität von Betriebssystemen sicherzustellen, die „nur“ zwei Modi unterstützen. Bei Virtualisierungs-Lösungen kommt dagegen oftmals Ring1 zum Einsatz, und zwar als „Kernel-Modus“ für die Gastsysteme, während Ring0 für den Kernel-Modus des Hypervisors vorgesehen ist. Ring3 kommt dann wieder für den User-Modus (Anwendungen auf der VM) zum Zuge. Seltener kommt Ring2 zum Einsatz, etwa werden unter OS/2 die Grafiktreiber an dieser Stelle betrieben.
Durch diese Vorgehensweise können die Informationen voneinander isoliert werden. Möchte nun eine Anwendung Zugriff auf einen bestimmten Speicherbereich, erhält die Software diesen. Allerdings wird dabei nur Zugriff auf einen entsprechenden Zeiger (wie bei einer Verknüpfung) gewährt, und nicht auf den physikalischen Speicherbereich. Auf diese Weise kann – dank dem Betriebssystem – sichergestellt werden, dass kein Prozess Daten auslesen kann, die nicht entsprechend freigegeben wurden. Wechselt die CPU nun von einem Modus in den anderen, geht etwas Zeit verloren. Ständige Wechsel (sogenanntes Kontext-Switching) hat dramatische Auswirkungen auf die CPU-Performance. Daher sind die Entwickler (hoffentlich) bestrebt, diese Wechsel möglichst gering zu halten.
Der jeweilige Status der einzelnen Speicherbereiche wird durch einen entsprechenden Schalter („CPU mode bit“) festgelegt. Ist das nicht Bit gesetzt (entspricht dem Wert „Null“), kann der jeweilige Bereich nicht ausgelesen werden (Kernel-Mode), ist das Bit dagegen gesetzt (Wert „Eins“) kann der Speicherbereich ausgelesen werden (User-Mode). Das Bit kann dabei nur verändert werden, wenn sich die CPU im Kernel-Modus befindet.
Viele CPUs (beinahe alle Modelle seit 2010) verfügen über eine spezielle Funktion, die bestimmte Dateien bereits in den Speicher laden, bevor diese benötigt werden. Daher lesen die betroffenen CPUs bereits Daten aus, die in den nächsten Augenblicken (vermutlich) für die Berechnungen nötig sind. Auf diese Weise befinden sich die Daten schon in der Pipeline, weitere Ladezeiten lassen sich vermeiden. Lädt die CPU allerdings Daten, die im Nachhinein nicht zum Zuge kommen, können diese einfach überschrieben werden.
Dank ausgefeilter Vorhersage-Algorithmen landen allerdings mit hoher Wahrscheinlichkeit Daten im CPU-Cache, die tatsächlich für die nächsten Rechenschritte wichtig sind. Dies wird vor allem durch die hohe Parallelität aktueller Systeme ermöglichst, so können quasi alle nicht benötigten Register und Cache-Bereiche der CPU-Cores für diese Vorhersagemethode eingesetzt werden. Sprich wenn drei Threads auf einer CPU mit acht virtuellen Kernen laufen, können bis zu fünf Cores für diese Technik eingesetzt werden. Und genau diese Technik nutzt die „Meltdown-Angriffsmethode“ aus. Das perfide daran: „Meltdown“ greift nicht etwa auf eine Sicherheitslücke von Softwarekomponenten, wie fehlerhafte Anwendungen oder unsauber programmierten Teiles des Betriebssystems zu, sondern attackiert direkt die CPU-Funktionen. Daher wird prinzipiell fast jedes System angreifbar. Egal ob auf dem System ein Linux- oder Windows-Betriebssystem läuft, oder ein Hypervisor installiert ist: Diese Sicherheitslücke lässt sich quasi „universell“ ausnutzen.