Meltdown und Spectre: Lesen ohne zu lesen
Risiken und Nebenwirkungen – Angriffe, ...
2. Risiken und Nebenwirkungen
Angriffe
Die Angriffe nutzen nun aus, dass nicht der ganze Zustand wiederhergestellt wird, sondern der Cache auch weiterhin die Werte enthält, welche durch die spekulativ ausgeführten Instruktionen geladen wurden. Sie nutzen diese auf drei unterschiedliche Weisen.
Meltdown: Rechteanmassung
Ein Programm darf nicht auf den gesamten Speicher zugreifen, sondern nur auf Bereiche, die ihm auch zugewiesen wurden. Intel macht in seinen Prozessoren diese Überprüfung zu spät. Sie findet nämlich nicht dann statt, wenn der fragliche Operand geladen werden soll, sondern erst wenn der Befehl in Pension gehen soll.
Dadurch kann ein Programmierer in spekulativen Instruktionen auf Speicherbereiche zugreifen, die er sonst gar nicht zu sehen bekäme. Er kann das Resultat aber nicht verwenden, denn die Resultate des Befehls werden weggeworfen. Er kann aber aufgrund des gelesenen Wertes in weiteren spekulativen Befehlen den Cache so verändern, dass später im Programm dann Rückschlüsse auf diese gelesenen Daten möglich sind.
Damit kann Speicher ausgelesen werden, auf den das Programm eigentlich gar nicht zugreifen dürfte. Da der Lesebefehl aber ja nicht wirklich (sondern nur spekulativ) ausgeführt wird, gibt es auch kein Problem.
Damit lassen sich auf Intel-Prozessoren Speicherbereiche des Betriebssystems oder von anderen virtuellen Maschinen auslesen – eine Gefahr für alle Cloud-Dienste.
Spectre 1: Indexgrenzenüberschreitung
Programme greifen regelmässig auf Felder (Arrays) zu: Sequenzen von Speicheradressen, die zusammengehörige Informationen enthalten und durch eine Startadresse und eine Länge definiert sind. Die einzelnen Positionen sind durchnummeriert (indexiert); nur Positionen bis zur maximalen Länge sind gültig.
Mittels zu grosser Indizes könnte auf Bereiche ausserhalb des Arrays zugegriffen werden, Bereiche, an denen sich andere Daten befinden. Deshalb finden – insbesondere in Programmen, die mit Indizes arbeiten, die von aussen beeinflusst werden können – Überprüfungen statt, ob der Index auch innerhalb des gültigen Bereichs liegt:
…
vergleiche index, maximaler_index
springe_wenn_grösser fehler_indexüberschreitung
lade array[index], register_x
…
fehler_indexüberschreitung:
# Fehlermeldung
vergleiche index, maximaler_index
springe_wenn_grösser fehler_indexüberschreitung
lade array[index], register_x
…
fehler_indexüberschreitung:
# Fehlermeldung
Der Spectre-1-Angriff greift nun genau hier ein: Da im Normalfall der Index im gültigen Bereich liegt, prognostiziert der Prozessor, dass der lade-Befehl ausgeführt werden soll und liest spekulativ aus dem ungültigen Bereich. Obwohl der Fehler später bemerkt wird und der gelesene Wert nie in einem normal zugreifbaren Register landet: Der Cache bleibt verändert und lässt durch sein Verhalten Rückschlüsse wie oben zu.
Spectre 2: Unterjubeln von Befehlen
In vielen Programmen werden sogenannte Sprungtabellen verwendet: Die Adresse des nächsten auszuführenden Befehls steht an einer spezifischen oder zu berechnenden Speicheradresse. Betriebssysteme und objektorientierte Programmiersprachen sind zwei fleissige Nutzer dieser Technik.
Beim Spectre-2-Angriff wird der Prozessor so vorbereitet, dass die Sprungvorhersage auf einen präparierten Codeblock zeigt. Auch hier werden die Befehle nur spekulativ ausgeführt, ihre Auswirkungen auf den Cache sind aber erkennbar.
Kernproblem
Das Kernproblem liegt darin, dass wir aus Effizienzgründen an vielen Stellen gemeinsame Ressourcen nutzen. Nicht nur im Prozessor, z.B. der Cache, sondern auch im Internet (gemeinsame Funkkanäle oder Leitungen), aber auch in der realen Welt (z.B. Schiene oder Strasse). Wenn mehrere Teilnehmer eine gemeinsame Ressource nutzen, können sie darüber miteinander kommunizieren, beispielsweise, indem der eine Teilnehmer die Auslastung dieser Ressource verändert und das Gegenüber diese Auslastung beobachtet. Damit wird diese Ressource zum Kommunikationskanal: einer von unzähligen verdeckten Kanälen oder Seitenkanälen.
Um diese Seitenkanäle zu nutzen, müssen beide Kommunikationspartner aktiv werden. Im Normalfall bedingt dies die freiwillige Teilnahme beider Seiten. In diesem Fall kann aber durch spekulative Ausführung (mit interner Umordnung der Befehle, «out-of-order execution») eine der beiden Kommunikationsseiten zur Zusammenarbeit übertölpelt werden. Damit wird die Spekulation nicht vollständig frei von Nebenwirkungen und damit entsteht die Möglichkeit eines Seitenkanals.
Das Problem besteht nur, solange gemeinsame Ressourcen und spekulative Ausführung zusammen auftreten. Beide sind aber Schlüsselstellen für die Effizienz der heutigen Prozessoren. Durch bessere Trennung des Caches für normale und spekulative Instruktionen (wie es schon heute für Schreibbefehle verwendet wird) könnte das erreicht werden. Durch die langen und teuren Entwicklungszyklen für Prozessoren werden wir erst in vielen Monaten mit Prozessoren rechnen dürfen, die das Problem nicht mehr haben.
Betroffen
- … von Meltdown sind laut aktuellem Informationsstand die meisten Intel-Prozessoren der letzten ca. 20 Jahre und einige neuere ARM-Prozessoren. Prozessoren anderer Hersteller, auch wenn sie x86-kompatibel sind, scheinen bisher nicht davon betroffen zu sein.
- … von Spectre 1 und 2 sind die meisten aktuellen Prozessoren, die spekulative Ausführung mit out-of-order execution verwenden, wenn auch in unterschiedlichem Ausmass. Insbesondere scheinen die meisten ARM-Prozessoren davon nicht betroffen zu sein. Insbesondere Spectre 1 scheint aber hauptsächlich Programme zu betreffen, die fremden Code ausführen. Prominente Beispiele sind da Webbrowser, die aber auch schon Gegenmassnahmen ergriffen haben.
Gegenmassnahmen
Alle drei Fälle basieren auf Fehlern der CPU; da Updates bei den CPUs jedoch schwierig sind und nur teilweise abhelfen, sind Betriebssysteme, Compiler und Anwendungsprogrammierer gefordert.
- Meltdown wird in vielen Betriebssystemen durch Änderung der Speicherorganisation verhindert. Bei jedem Betriebssystemaufruf sind neu teure Änderungen der Übersetzungstabelle notwendig. Dies führt jedoch zu Verlangsamungen, je nach Situation zwischen rund 5 % und 30 %, sehr selten bis fast 50 %.
- Spectre 1 (Arraygrenzen) wird zuallererst die Programmierer beschäftigen. Sie müssen sicherstellen, dass – wenn sie nicht vertrauenswürdigen Code in ihrer Anwendung ausführen – dieser dann (a) den Seiteneffekt nicht auslösen kann oder (b) ihn nicht messen kann. Vermutlich werden in den nächsten Monaten findige Entwickler von Compilern Optionen schaffen, um diese Situation automatisch zu erkennen und zu verhindern.
Da die Lücke aber nur Anwendungen betrifft, die fremden Code ausführen (JIT, Bytecode und eventuell auch Interpreter), aber alle Anwendungen verlangsamen, werden die betroffenen Anwendungsentwickler diese Funktion des Compilers wahrscheinlich zuerst aktivieren müssen. - Spectre 2 (Berechnete Sprünge) wird aktuell über Microcode- in Kombination mit Betriebssystem-Updates behoben. Alternativ kann auch sogenannter «RetPoline»-Code anstelle des berechneten Sprungs genutzt werden. Einige Compiler bieten bereits eine entsprechende Option an, Weitere werden folgen.
Wir sehen, dass nur eine Kooperation aller Akteure (CPU-Hersteller, Betriebssystemmacher, Compiler-Entwickler und Anwendungsprogrammierer) das Problem nachhaltig lösen kann, zumindest solange keine Meltdown- und Spectre-sicheren neuen Prozessoren verfügbar sind.
Bis die Sache ausgestanden ist, werden auch die Nutzer stark gefordert: Das fleissige und zeitnahe Einspielen von Anwendungs-, Betriebssystem- und BIOS/UEFI-Updates [3] sowie das Ausbaden unerwünschter Nebenwirkungen derselben werden dafür sorgen, dass uns allen noch über Monate hinweg nicht langweilig wird.
Weiterführende Informationen
Deutsch:
• FAQ zu Meltdown und Spectre (Heise), inklusive vieler Links
• Benchmarks (Heise)
• Deutsche Erklärung (Proact)
Englisch:
• Webseiten zu den Spectre- und Meltdown-Attacken inklusive technischer/wissenschaftlicher Literatur (derzeit sind die beiden Webseiten bis auf das Favicon identisch)
• Performanceanalysen von Phoronix und Andreas Freund (Postgres)
• Erster Überblick über die Sicherheitslücke sowie Hintergründe und Entstehungsgeschichte (The Register)
• Englische Erläuterung, inklusive Begründung, wieso der Raspberry Pi nicht betroffen ist
• Beschreibung der Sicherheitslücken für Programmierer (Google Project Zero)
• Test-Software, ob ein Linux-Rechner verwundbar ist
• Erläuterung zu RetPoline (Google)
• Caching war schon ein Problem in der Xbox 360
Bildquellen
• Schachspiel: Wikipedia-Eintrag «Chess», Spiel zwischen Botvinnik und Yudovich (1933).
• Grafiken: Marcel Waldvogel
Fussnoten:
[1] Alternativ könnte er auch mit einer Wärmebildkamera die zuletzt angefassten Figuren identifizieren oder, oder, oder …
[2] Es gab einen Trend zu Prozessoren mit einfacheren Befehlen, die dann entsprechend schneller ausgeführt werden können (RISC-Prozessoren, insbesondere die in Mobilgeräten beliebten ARM-Prozessoren). Aber die klassischen CISC-Prozessoren mit ihrer grösseren Verbreitung und Marktmacht haben da einfach aufgeholt, indem sie intern wie RISC zu arbeiten begannen.
[3] Leider sind BIOS-/UEFI-Updates häufig nicht so einfach einzuspielen wie der Rest. Hier sind die Gerätehersteller gefordert.
Über den Autor und den Beitrag
Der Originaltext stammt vom Weblog von Marcel Waldvogel, der uns freundlicherweise erlaubt hat, den Text zu verwenden.
Marcel Waldvogel ist Spezialist für IT-Sicherheit und Informatikprofessor an der Universität Konstanz. Er bedankt sich bei Patrick Stählin («Schach»), Matthias Fratz und Gaby Salvisberg für Ideen, Diskussionen und Korrekturen.
18.01.2018
18.01.2018
22.01.2018
22.01.2018