Der Hammer mit dem Rowhammer

Wissenschaflter weisen nach: ein Klick auf eine Website reicht mitunter, um irgendwo Bits im Rechner kippen zu lassen.

In Pocket speichern vorlesen Druckansicht 1 Kommentar lesen
Lesezeit: 5 Min.
Von
  • Andreas Stiller

Viel Aufsehen machte schon vor einiger Zeit der sogenannte Rowhammer-Angriff, konnte Google-Entwickler Mark Seaborn doch zeigen, dass man eine seit 2012 bekannte Anfälligkeit von DRAMs ausnutzen kann, um sich mit einer bestimmten Trefferquote Root-Rechte unter Linux zu verschaffen oder aus einer Chromium-Sandbox auszubrechen. Nun haben Wissenschaftler der Uni Graz das weiter ausgedehnt und nachgewiesen, dass unter bestimmten Voraussetzungen sogar ein Javascript-Code etwa unter Firefox Hardware-Fehler provozieren kann (Rowhammer.js A Remote Software-Induced Fault Attack in JavaScript auf Arxiv.org)

Die Anfälligkeit beruht auf der Tatsache, dass eine Fülle aufeinanderfolgender Lesezugriffen auf ein und dieselbe Speicherzeile (row) gelegentlich Bits in der benachbarten Zeile kippen lassen kann, Bits, die an Seitengrenzen auch zum allozierten Speicher anderer Applikationen oder zum Betriebssystem gehören können. Bei Servern mit Fehlerkorrektur (ECC) werden die Bitfehler in aller Regel erkannt und korrigiert, da greift dann die Attacke ins Leere. Bei Desktop-PCs und Notebooks hingegen, lassen sich durch die Rowhammer-Attacke mehr oder weniger gezielt Bits irgendwo im Speicher kippen und für böswillige Zwecke missbrauchen.

Vorteilhaft für so einen Angriff ist eine genaue Kenntnis der Lage der physischen Adressen der Arrays in der attackierenden Rowhammer-Applikation und von den Angriffszielen, etwa den Seitentabellen des Betriebssystems. Ansonsten stochert man im Nebel herum, gleicht aber einem wild um sich herumschießenden Attentäter, der schon irgendetwas Wichtiges treffen wird. Erste Gegenmaßnahme von Linux war dann auch, den User-Programmen Zugriff auf die Informationen über das Speichermapping etwa auf /proc/PID/pagemap zu verbieten

Um die Fülle von Lesezugriffen in kurzer Zeit auf gleiche oder benachbarte Speicherzellen hinzubekommen, muss man irgendwie den Cache-Mechanismus austricksen. Dafür gibt es viele Möglichkeiten, am einfachsten geht’s mit dem CLFLUSH-Befehl, den alle neueren Prozessoren bieten und der, anders als der WBINVD-Befehl, ungeschützt im Usermode verfügbar ist. Mit CLFLUSH kann man zudem gezielt einzelne Cache-Lines flushen. Wenn diese nicht verändert wurden, wird auch nichts in den Speicher zurückgeschrieben, was für Rowhammer kontraproduktiv wäre.

Kennt man die Cache Replacement Strategien der einzelnen Caches kann man aber auch mit gezielten Zugriffen ohne CLFLUSH dafür sorgen, dass die Cacheline geflusht wird. Solche Strategien hat schon das uralte Cachemess-Programm von c't damals noch unter DOS verwendet. Aber damals waren anders als heute die Cache-Replacement-Strategien (zumeist ein nicht ganz vollständiger Least Recenty Used (LRU) mit nur zwei zusätzlichen Tag-Bits) und auch das Mapping der Speichercontroller bestens dokumentiert. Und unter DOS hatte man es ja zudem von Haus nur mit physischen Adressen zu tun.

Heutzutage gibt es insbesondere für Intel-Prozessoren nur marginale Dokumentationen, aber findige Programmierer konnten das meiste durch gewiefte Programme austüfteln. Die Strategien erweisen sich als durchaus unterschiedlich für Sandy Bridge, Ivy Bridge und Haswell.

Die Grazer Wissenschaftler haben aber nun eine Adaptive Cache Eviction Strategy entwickelt, die mit geschickt gewählten Zugriffssequenzen alle drei Architekturen mit hoher Trefferquote adressieren. Dann braucht man keinen nativen Code, auch Java, Javascript oder .Net-Programme können solche Zugriffssequenzen in Feldern durchführen. Javascript ist dabei besonders prekär, ist es doch normalerweise in den Browsern aktiviert. Da reicht ein Klick auf eine Website und schon sind Bits im Rechner gekippt. Den Code haben die Wissenschaflter auf Github gestellt (rowhammerjs).

Ganz so einfach ist es allerdings doch nicht. Beim Haswell-Prozessor i7-4790 im Asus H97-Pro mit normaler Refreshrate passierte bei den Grazer Autoren gar nichts, erst bei künstlicher Refresh-Verlangsamung über BIOS-Setup war der Javascript-Rowhammer erfolgreich. Der Erfolg des Hammern überprüft das Programm, indem es die Daten an den vermuteten Nachbarzeilen überprüft. Um aber einigermaßen zu wissen, wie man denn Cache-Kollisionen provoziert und wo die jeweiligen Speicherzeilen im Adressraum eingeblendet sind, braucht man schon Kenntnis über ein paar Bits mehr als die 12 Bit einer üblicherweise 4K großen Speicherseite, sonst stochert man zu sehr im Nebel herum. Die Autoren berichten von ihrer Beobachtung, dass Javascript größere Felder in 2 MByte Pages alloziert:"We observed that large typed JavaScript arrays are allocated on anonymous 2MB pages". Dann hat man schon Kenntnis über 21 Bit der physischen Adresse. Ein paar weitere Bits kann man dann erraten beziehungsweise ausstoppen.

Das geht aber wohl nur bei aktivierten Huge Pages oder bei Transparent Huge Pages, wie sie moderne Linux-Kernel bieten. Unter Windows muss man sich solche "Huge Pages" erst mit der lokalen Sicherheitsrichtline/Zuweisung von Benutzerrechten unter "Sperren der Seiten im Speicher" freischalten. Im Normalfall dürfte es der Javascript-Angriff hier um einiges schwerer haben.

Dennoch, man kann sich sogar Szenarien vorstellen, wo man mit Javascript per Rowhammering die eigene Pagetable modifiziert und darüber Zugriff auf den gesamten physischen Speicher bekommt – daran arbeiten die Autoren jetzt. (as)