Was Sie von Side-Channel-Angriffen lernen können
Cloud-Infrastrukturen haben Plattformen für die Entwicklung von Anwendungen geschaffen, die Entwicklern im gesamten Stack wertvolle Tools an die Hand geben. Allerdings macht es diese neu gewonnene Freiheit auch schwieriger zu bestimmen, welche Komponenten unserer Anwendungen wir mithilfe dieser Plattformen von Grund auf selbst programmieren und für welche wir einen Service abonnieren. Ein wichtiger Punkt, den man berücksichtigen muss, um herauszufinden, wo man beim Anwendungsdesign die Grenze zwischen „selbst bauen“ und „abonnieren“ ziehen soll, ist sicherzustellen, dass die gesamte Plattform vor Risiken geschützt ist.
In puncto Sicherheit gibt ein bekanntes Sprichwort: „Entwickle nie deine eigene Kryptographie.“ Das ist nach wie vor ein solider Ratschlag, aber „Entwickle nie deine eigene Plattform“ sollte die Fortsetzung davon sein. Die Architektur einer Plattform birgt so viele Kombinationsmöglichkeiten, dass ihre Anwendungsbereiche geradezu darum betteln, von Angreifern ausgenutzt zu werden – und Angreifer sind sehr clever. Eine Plattform einzurichten, ist nichts, was man mal eben so tut und was dann fertig ist, sondern es ist eine Aufgabe, die sich ständig weiterentwickelt. Und eine Plattform wie die von Fastly, bei der Computing-Services mit Caching- und Netzwerkservices von vornherein integriert werden, ist gut geeignet, immer komplexere Angriffe abzuwehren.
In diesem Blogpost werfen wir einen genaueren Blick darauf, was so alles schiefgehen kann. Die größte Kategorie schwer vorhersehbarer Schwachstellen bei der Gestaltung von Sicherheitslösungen bilden Side-Channel-Angriffe. Derartige Schwachstellen können auftreten, wenn ein Algorithmus zwar für sich genommen sicher ist, aber mit seiner Umgebung auf unerwartete Weise interagiert, sodass Angreifer Rückschlüsse auf seine vertraulichen Komponenten ziehen können.
Zunächst einmal nehme ich Sie mit auf einen kurzen, aber lehrreichen Rundgang durch einige der grundlegenden und ausgefallenen Side-Channel-Angriffe, die das Sicherheitsbewusstsein im Laufe der Jahre geprägt haben. Ich werde mich dabei aufs Wesentliche beschränken, aber wenn Sie sich genauer mit diesem Thema befassen möchten, finden Sie im Text die entsprechenden Links.
Ein skurriles Beispiel zum Einstieg
Beginnen wir unsere Tour mit einem Klassiker, der uns (mindestens) bis in die 80er-Jahre zurückwirft. Auch wenn Van Eck Phreaking heute größtenteils von historischem Interesse ist, dient es als hervorragendes Beispiel für Side-Channel-Angriffe. Die wichtigste Erkenntnis aus diesem Angriff war, dass ein Computermonitor als Nebeneffekt der Bilddarstellung elektromagnetische Felder (EMF) erzeugt. Die meisten von uns würden das höchstens als statisches Rauschen im Radio wahrnehmen, aber ein entschlossener Angreifer kann anhand dieses Rauschens ziemlich konkrete Rückschlüsse auf den Monitor selbst ziehen. Sogar bei einem nicht vernetzten Computer in einem Raum ohne Fenster bildet das Aussenden eines Lichtstrahls durch einen Computermonitor einen ausbeutbaren Side Channel. Wenn man darüber nachdenkt, wie absurd das ist, bekommt man ein Gefühl für die Komplexität des Problems.
Diese Nebeneffekte sind wahnsinnig schwer vorherzusagen und werden mit der Zeit immer raffinierter. Eines meiner liebsten Beispiele, bei dem es zugegebenermaßen weniger um Computersicherheit als um physische Sicherheit geht, wurde erst diesen Sommer veröffentlicht. Forschern gelang es, anhand von Audioaufnahmen eines Schlüssels, der in ein Schloss gesteckt wird, mit einem 3D-Drucker den passenden Schlüssel herzustellen! Die Geräusche, die der Schlüssel im Schloss erzeugt, wurden dabei zum Side Channel. Wie gut, dass wir nicht alle Mikrofone in unseren Taschen oder in unserer Küche haben, die alles mithören.
Timing ist alles
Uhren eignen sich ebenfalls hervorragend als Side Channel. Es ist auch nicht schwer zu verstehen, warum sie versehentlich Informationen preisgeben können, auf die der Sicherheitsalgorithmus nicht eingestellt ist. Der Raccoon-Angriff ist ein jüngerer Vertreter dieser Angriffskategorie, für die es zahlreiche Präzedenzfälle gibt.
Er nutzt eine Schwachstelle in einem ziemlich versteckten Teil von TLS 1.2 und früheren Versionen aus, deren Spezifikation für gängige Varianten vorschreibt, dass alle führenden Nullen eines geheimen Werts verworfen werden, bevor ein Hash ausgeführt wird – und zwar auf dieselbe Weise, wie man in Erwägung ziehen würde, die führenden Nullen einer Nummer wie 00314159 zu verwerfen, bevor man sie auf dem Bildschirm anzeigt. Der Timing-Angriff erfolgt, weil die Berechnung des Hashes einfacher (und damit schneller) ist, wenn sie mit 314159 ausgeführt wird als mit 00314159. So kann der Angreifer von einer oder zwei führenden Nullen ausgehen und etwas über die geheime Eingabe erfahren, indem er einfach auf die Uhr schaut und die TLS-Geschwindigkeit misst.
In den letzten Jahren waren Caches aller Art die Hauptquelle für Timing-Analysen von Side-Channel-Schwachstellen. Caches speichern absichtlich das Ergebnis vergangener Berechnungen, sodass sie in Zukunft schneller abgerufen werden können. Leider kann das dazu führen, dass zwischen Geräten, die die Historie der jeweils anderen Geräte nicht kennen sollen, Informationen durchsickern.
Ein großartiges Beispiel dafür ist der Cache eines Webbrowsers. Zu den Hauptaufgaben eines Browsers gehört es, verschiedene Websites voneinander getrennt zu halten. Der Browserverlauf auf Website A geht Website B nichts an. Allerdings kann Website B möglicherweise feststellen, ob sich Website A in Ihrem Cache befindet, indem sie selbst eine Subressource von Website A lädt und beobachtet, wie lange sie zum Laden braucht. Sehr schnelle Ladezeiten deuten darauf hin, dass sich die Seite in Ihrem Cache befindet und Sie schon einmal dort waren. Damit wird die Ladedauer aus dem Cache zu einem Side Channel und immer mehr Arten von Caches werden von der „First Party“ (also der Website, die das Laden auslöst) doppelt verschlüsselt. Dadurch erhöht sich zwar der Schutz der Daten, allerdings sinkt auch die Effektivität des Caches.
Dass Cache-Einträge Fingerabdrücke hinterlassen, geschieht auf allen Layern, da Caches nützliche Hilfen bei der Implementierung sind. Sie sorgen auf transparente Weise für eine Steigerung der Performance. Aber genau aufgrund dieser Transparenz können Informationen ungewollt durchsickern. Nicht nur clientseitige Anwendungen wie Browser, sondern auch serverseitige Multi-Tenant-Architekturen haben dieses Problem. Pythia nutzt das transparente Caching von Seitentabellen in der RDMA-Hardware, die für den effizienten Storage-Zugriff im Datacenter und Cluster-Computing verwendet wird. Dieser Angriff erfolgt nach dem üblichen Muster: zwei Services, die eigentlich voneinander isoliert sein sollten, erforschen den Verlauf des jeweils anderen, indem sie die Antworten auf ihre eigenen Anfragen so sorgfältig timen, dass sie Rückschlüsse ziehen können, ob einige Informationen durch die Aktionen der anderen Partei im Cache zwischengespeichert wurden oder nicht.
Turtles all the way down (oder: Das Problem des unendlichen Regresses)
Wie bereits erwähnt, sind viele dieser Probleme in den Abstraktionen verwurzelt, die notwendig sind, um die Technologien überhaupt ins Leben zu rufen. Echte Hardware bis zum Ende des Stacks sorgt also bei manchen Systementwicklern durchaus für ein beruhigendes Gefühl. CPUs, Chips, RAM – allesamt gute alte Von-Neumann-Architekturen auf die man sich verlassen kann! Aber das ist natürlich nur eine Illusion, denn dabei kann es sich auch um virtuelle Maschinen handeln, oder um Geräte mit eigenen Subprozessoren oder veränderbaren Mikrocodes oder sogar mit bedeutenden Abstraktionen, die ihre eigene Komplexität in leichter kontrollierbare Teile zerlegt. Man spricht dabei auch von Turtles all the way down oder dem Problem des unendlichen Regresses. Die Integrationsprobleme gehen also weiter. Wenden wir uns nun den scheinbar grundlegenden Komponenten zu: der CPU, dem RAM und dem Netzwerk.
An dieser Stelle können Sie vielleicht schon die berühmt-berüchtigte Geschichte der als Spectre bekannten Transient-Execution-Angriffe erkennen. Ein Großteil von Spectre ist bereits bekannt, da bei dieser Angriffsart Spuren in der Cache- und Timing-Analyse hinterlassen werden. Spectre geht aber noch einen Schritt weiter, indem es diese Dinge mit dem internen Verhalten der CPU verknüpft. Schwachstellen in der Kernlogik des Prozessors sind Geschenke, die Angreifern immer wieder gemacht werden. Bei einer fehlgeschlagenen spekulativen Ausführung während eines Spectre-Angriffs kommt es zu Veränderungen im Cache. Das bedeutet praktisch, dass die CPU im wahrsten Sinne des Wortes berechnet, was passiert wäre, wenn etwas anderes als das, was wirklich passiert ist, passiert wäre, nur für den Fall, dass es passiert.
Das ist Verwirrung à la Schrödingers Katze, aber das Problem ist, dass diese Hypothese auf CPU-Ebene Spuren im prozessoreigenen Cache hinterlässt, die durch Timing-Angriffe ähnlich wie bei anderen oben beschriebenen Cache-Angriffen in die Hände des falschen Codes geraten können. Es handelt sich hierbei nicht um einen einzelnen Angriff, sondern um eine ganze Reihe von Gefahren, die sich ständig weiterentwickeln und auf kurze Sicht im Grunde eine durchdachte, ganzheitliche und tiefgreifende Abwehrstrategie erfordern.
Während es bei den meisten Side Channels darum geht, dass Angreifer an Daten gelangen, auf die sie eigentlich keinen Lesezugriff haben sollten, erhalten sie mit einigen verwandten Ansätzen sogar Schreibzugriff. Ein klassisches Beispiel für einen solchen Ansatz ist Rowhammer. Dabei belastet ein Angreifer absichtlich einen Teil des RAMs so stark, dass die elektrischen Impulse auf den benachbarten RAM einwirken, ohne dass das Betriebssystem oder die Anwendung sich darüber Gedanken machen, ob es sich hier um eine sichere Sache handelt oder nicht. Dies wird oft als ein Störangriff angesehen, bei dem der Zugriff auf den benachbarten RAM als Side-Channel-ähnlicher Durchlass für den Angriff dient.
Da es so gerissen und schlau ist, einen ungewöhnlichen Side Channel zu nutzen, möchte ich noch auf einen weiteren Angriff eingehen. Wenn ich darüber nachdenke, erinnert mich das daran, immer offen zu sein in Bezug auf das, was ich zu wissen glaube. Dieser Angriff stützt sich nicht auf etwas so Banales wie einen gemeinsamen Cache von Angreifer und Opfer, sondern nutzt den gemeinsamen Netzwerkpfad, den beide über den drahtlosen Heim-Router des Opfers verwenden könnten.
TCP gilt im Allgemeinen als unsicher gegenüber On-Path-Angreifern aber robust gegenüber Off-Path-Angriffen. Wenn der Angreifer also nicht in der Lage ist, den Traffic zwischen Client und Server zu lesen (das heißt, wenn er sich außerhalb des Netzwerkpfads befindet), sollte er die Verbindung nicht manipulieren können. Die ausnutzbaren geheimen Informationen, die abseits des Pfades nicht verfügbar sind, sind die 48 Bit der Client-Portnummer in Kombination mit der entsprechenden TCP-Sequenznummer. Wenn der Angreifer diese Informationen erhält, kann er damit leicht beliebige Daten einschleusen oder sogar nach Belieben eine Off-Path-Verbindung beenden.
Der Trick bei diesem Angriff ist, dass das Opfer mit unterschiedlich großen Antworten auf die vom Angreifer gesteuerten Abfragen der geheimen Informationen reagiert, je nachdem, ob der Angreifer richtig lag, weit daneben oder doch schon näher dran. Normalerweise würde das keine Rolle spielen, weil der Off-Path-Angreifer die verschiedenen Antworten nicht sehen kann, aber wenn der Angreifer parallel zu den Angriffen eine separate Verbindung mit dem Opfer herstellt, kann er die Auswirkungen der versteckten Nachrichten auf eine gemeinsam genutzte Instanz, den WiFi-Router, messen. Größere Nachrichten auf dem Off-Path-Kanal verlangsamen die Nachrichten auf dem On-Path-Kanal erkennbar, und das liefert ausreichend Rückschlüsse darauf ob richtig geraten wurde. So spielt der Angreifer ein „Heiß-oder-kalt“-Spielchen und kann den geheimen Raum schnell durchdringen, anstatt den gesamten Raum auf der Suche nach einer exakten Übereinstimmung erkunden zu müssen. Ganz schön clever, oder?
Fazit
Dies sind alles gute Beispiele für Dinge, die vielleicht nicht unbedingt offensichtlich sind, wenn man mit einem Do-it-yourself-Projekt anfängt. Jedes dieser Beispiele – und das ist nur ein kleiner Vorgeschmack auf all die Möglichkeiten – ist überaus clever und man sollte Respekt davor haben. Ich würde es viel lieber sehen, wenn Sie sich um die kreativen Teile der Anwendungserstellung kümmern und eine integrierte Edge-Cloud-Plattform nutzen, die konzipiert, skaliert und gewartet wird, um diese Art von Anwendungen zu unterstützen, ohne ständig Ihre Energie zu beanspruchen.
Anwendungen vor solchen Schwachstellen oder anderen Anfälligkeiten wie diesen zu schützen, ist eher ein Prozess als ein einzelnes Ereignis: Betrachten Sie aufmerksam den gesamten Kontext der Anwendung, dokumentieren Sie die Risiken, sorgen Sie für Abwehrmaßnahmen, wo immer Sie können, definieren Sie ABIs, die Zeit, Raum und Datendefinitionen berücksichtigen, und überprüfen und überarbeiten Sie sie kontinuierlich. „Abschicken und vergessen“ wird mit der Zeit zu Anfälligkeiten führen. Selbst das umsichtigste Patching, so wichtig es auch ist, kann Umgebungskombinationen übersehen, die den Kern von Exploits bilden. Entwickler einzelner Komponenten haben auch nur einen begrenzten Einblick in das Problem. Die Einrichtung einer Plattform ist ein Vollzeitjob.