Lauschangriff

Hyper-Threading birgt ein potenzielles Sicherheitsrisiko, da man darüber verdeckte Informationskanäle aufbauen und andere Software zumindest in gewissem Rahmen belauschen kann.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 6 Min.
Von
  • Andreas Stiller
Inhaltsverzeichnis

Manche Sicherheitsexperten, etwa von OpenSSL, Red Hat, BSD oder Sun-Solaris, haben hektisch reagiert und die Lücke gestopft, die der kanadische Student Colin Percival proklamiert hat [1]. Eigentlich sind es gleich zwei Lücken, um die es hier geht. Zum einen um einen geheimen Informationskanal (covert channel) zwischen zwei gleichzeitig auf der Maschine laufenden Prozessen, zum anderen um das Abhören sicherheitsrelevanter Software, beispielsweise bei der Erzeugung eines RSA-Schlüssels.

Wann immer sich Prozessoren beziehungsweise Prozesse Ressourcen teilen, gibt es auch das Risiko, dass darüber trickreich Informationen auf unüblichem Wege ausgetauscht werden können, sei es via Festplatte, Grafikkarte, Netzwerk, Drucker, Hauptspeicher oder eben auch über die Prozessor-Caches. Schon in den siebziger Jahren [2] wurden diverse Szenarien beschrieben, wie über timing channels per Zeitmessung Informationen verschickt und eine quasi-synchrone Kommunikation aufgebaut werden kann.

Dank der präzisen Messmöglichkeiten heutiger Prozessoren mit dem Time Stamp Counter (TSC) sind diverse, schnelle Morse-Kanäle über das Timing von Zugriffen denkbar - das gilt generell für alle Prozessoren. Das Hyper-Threading schafft aber eine weitere, interessante Möglichkeit.

Beim Hyper-Threading teilen sich zwei logische Prozessoren bis auf den Registersatz fast alle Ressourcen, insbesondere auch den L1-Cache. Der wird nicht starr Hälfte/Hälfte aufgeteilt, sondern steht beiden dynamisch zur Verfügung - ein Prozess kann dann die Cache-Einträge des anderen herausschmeißen. Als Performance-Problem hat Intel das schon lange als Cache-Aliasing-Konflikt benannt und gezeigt, wie dieser mit ein paar Maßnahmen weitgehend vermieden werden kann. Umgekehrt lässt sich der Konflikt aber auch absichtlich provozieren, um heimlich Daten zu übertragen. Der sendende Prozess erzeugt einfach ein bestimmtes Konfliktmuster mit Cache-Hits und -Misses und der im zweiten logischen Prozessor parallel mitlaufende Empfangsprozess stoppt die Ladezeit der Cache-Lines aus und bekommt so die Daten herübergemorst - egal mit welchen Rechten die Prozesse laufen. Beiden Prozessen reichen dafür die User-Rechte auf Ring 3 völlig aus, denn das Lesen des Time Stamp Counters ist üblicherweise freigeschaltet. Hätten die Prozesse Administrator- oder Treiberladerechte, bräuchte man die umständliche Cache-Funkerei gar nicht erst zu bemühen - hierfür gäbe es weitaus einfachere „geheime“ Kanäle.

Ganz ungestört ist der Cache-Funk-Kanal zwar nicht - Interrupts können dazwischenfunken, der Hardware-Prefetcher des Prozessors ebenfalls und die Messung selbst stört auch - aber es gibt ja fehlerkorrigierende Codes, die gerade für solche stark gestörten Übertragungskanäle ausgelegt sind.

Ganz so einfach, wie es Percival in seinem Papier [1] darlegt, ist der L1-Daten-Cache des P4 allerdings nicht strukturiert. Er ist nicht nur vierfach (oder jetzt achtfach) assoziativ, sondern arbeitet auch mit einer Strategie, die sich „virtually addressed/physically indexed“ nennt. Zum Belauschen ist das nützlich, denn auf Grund der virtuellen Adressierung teilen sich zwei Prozesse mit der gleichen virtuellen Adresse dieselbe Cache-Line. Die Adresse muss nicht einmal ganz übereinstimmen, es reichen die unteren 16 (bei älteren P4-Versionen) oder inzwischen 22 Bit. Für ein akkurates Ausstoppen von Ladezeiten wäre die Kenntnis sowohl der virtuellen als auch physischen Adressen wünschenswert, an letztere kommt aber nur ein Kernel-Treiber heran. Ein User-Programm kann sich nicht darauf verlassen, dass es beim Allozieren eines Speicherblocks einen physisch zusammenhängenden Bereich zugewiesen bekommt. Windows XP beispielsweise verwirbelt die einzelnen Pages kräftig. Das macht die Sache sehr komplex und es ist fragwürdig, ob das von Percival veröffentlichte Codefragment wirklich funktioniert. Mit einiger Mühe konnten wir immerhin mit eigener Software per Cache-Aliasing-Konflikten unter Windows XP auf einem Prescott-Prozessor ein paar Bits übertragen.

Über das L1-Context-Bit im Konfigurationsregister lässt sich überdies auch eine andere Cache-Strategie einstellen, bei der sich nur noch Threads desselben Prozesses eine Cache-Line teilen. Dennoch gibt es auch hier einen Verdrängungswettbewerb im gemeinsam genutzten L1-Cache, den man mit etwas Fantasie für Morsezwecke missbrauchen könnte. Und außerdem, so Percival, lässt sich die Hit/Miss-Idee auch auf den L2-Cache ausdehnen. Der arbeitet allerdings mit physischer Adressierung, was die Sache um einiges erschwert.

Zu allem Übel gibt es dank Hyper-Threading noch die Lauschmöglichkeit zwei: Ein Spionageprozess von User A belauscht anhand des Cache-Fußabdruckes beispielsweise die RSA-Schlüsselerzeugung von User B - das dürfte dem nicht besonders recht sein und erfordert nicht einmal einen Trojaner.

Mit Hilfe von OpenSSL zeigte Percival auf, dass bei der Schlüsselgenerierung (RSA_Generate_key) charakteristische, belauschbare Cache-Muster entstehen, die bei Kenntnis des Algorithmus (ist ja Open Source) Rückschlüsse auf einen Teil des generierten Bitmusters gestatten - und wenn von 512 Bit schon mal 300 gut geraten werden können, ist der Schlüssel nicht mehr viel wert. Auch ohne Source-Code- und Algorithmus-Kenntnisse könnte man ein gutes neuronales Netz mit Schlüsseln und Cache-Mustern trainieren. Es gibt aber eine Fülle brauchbarer Abwehrmaßnahmen - man muss sie nur einsetzen. Der Programmierer kann beispielsweise sicherheitsrelevante Daten und gegebenenfalls auch den Code in ungecachete Bereiche verlagern (unter Windows mit VirtualAlloc (... PAGE_NOCACHE), was jedoch Performance kostet. Beim OpenSSL-Patch (0.9.7h) wurde stattdessen der Algorithmus so verändert, dass das Zugriffsmuster unabhängig vom Bitmuster wird und sich so keine Rückschlüsse mehr ziehen lassen. Betriebssysteme könnten während der critical sections parallel laufende Prozesse suspendieren. Auch die Verwirbelung von Ladeadressen, (address obfuscation), wie sie einige Betriebssysteme zur Vermeidung von Buffer-Overflow-Exploits durchführen, kann helfen. Der Prozessorhersteller könnte mit einer geänderten Cache-Strategie solche Lauschzugriffe abblocken. Oder man überlässt eben solche wichtigen Dinge wie die Schlüsselerzeugung abhörsicherer Hardware, die sich damit auskennt: den Trusted Platform Modules (TPM).

[1] Colin Percival, Cache Missing for Fun and Profit

[2] National Computer Security Center, A Guide to understandig Covert Channels (as)