Neue Besen kehren gut, sagt man. Aber sind sie auch sicher?

WebAssembly – Ist das sicher oder kann das weg?

WebAssembly – Ist das sicher oder kann das weg?

Neue Besen kehren gut, sagt man. Aber sind sie auch sicher?

WebAssembly – Ist das sicher oder kann das weg?


Wie sicher ist der Neuankömmling WebAssembly eigentlich? Dieser Frage geht Carsten Eilers in seinem Artikel mit einer ganzen Reihe aktueller Beispiele nach.

Schon wieder eine neue Technologie für aktive Inhalte – muss das denn wirklich sein? Als hätten wir mit Flash und Java nicht schon genug Ärger gehabt. Beides wurde wahrscheinlich öfter für Angriffe als für wirklich nützliche Anwendungen verwendet. Jedenfalls wenn man mal von Spielen und in der Websteinzeit dem Wiedergeben von Videos durch Flash absieht. HTML5 und die dazugehörenden JavaScript-APIs decken doch schon alle möglichen und unmöglichen Anwendungsfälle ab. Wieso also noch was Neues erfinden? Vor allem, wo doch jede neue Funktionalität immer auch die Angriffsfläche erhöht, die man doch eigentlich möglichst klein halten möchte. Die Antwort ist ganz einfach: Wieso nicht? Vielleicht ist das Neue ja besser als alles Alte.

Wichtig ist natürlich vor allem, dass es sicher ist. Nicht nur sicherer als Flash oder Java – das ist keine Kunst, so chronisch unsicher wie die sind. Sondern wirklich sicher, von Anfang an und ohne Kompromisse. Wobei Java in der Theorie auch sicher sein sollte, nur bei der Umsetzung, vor allem im Browser, hat es dann gewaltig gehakt. So sehr, dass Java im Browser inzwischen im Grunde tot ist.

Wie sieht es also mit der Sicherheit von WebAssembly (auch kurz „Wasm“ genannt) aus? Dazu schauen wir uns erst einmal an, was das überhaupt ist. Und zwar nur im Kontext von Webanwendungen und der Ausführung im Webbrowser, denn das ist der primäre Anwendungszweck. Dass WebAssembly auch in Nicht-Webumgebungen ausgeführt werden kann, ist laut den WebAssembly-Entwicklern zwar wünschenswert, aber kein zentrales Ziel der Entwicklung.

WebAssembly ganz einfach …

Sehr vereinfacht gesagt ist WebAssembly ein Bytecode, der in einer Sandbox ausgeführt wird. Im Browser werden WebAssembly-Module in der JavaScript-VM ausgeführt. Für den WebAssembly-Code gelten daher die gleichen Sicherheitsbeschränkungen wie für JavaScript-Code, insbesondere also die Same-Origin Policy. Hinzu kommt die zusätzliche Einschränkung, dass WebAssembly-Code nicht direkt auf das DOM der Seite zugreifen kann. Für Änderungen an der dargestellten Seite oder das Abfragen von Informationen daraus müssen JavaScript-Funktionen verwendet werden. Auch können die WebAssembly-Module nur dann auf die Hardware oder das Dateisystem zugreifen, wenn der Benutzer das in der Browserkonfiguration explizit erlaubt.

… und etwas formaler

Formal betrachtet ist WebAssembly die Spezifikation einer Instruction Set Architecture und eines Dateiformats. Die Instruction Set Architecture beschreibt einen (virtuellen) Rechner, und das Dateiformat legt den Aufbau von WebAssembly-Modulen fest. Der Browser lädt den WebAssembly-Binärcode in Form von Modulen und führt ihn aus.

Das ähnelt den bekannten Java-Applets, die zu Java-Bytecode kompiliert und in der Java Virtual Machine (VM) ausgeführt werden. Der Unterschied besteht darin, dass Java-Applets eine Erweiterung des Browsers sind, die in einem Plug-in ausgeführt werden, während WebAssembly-Bytecode, wie schon erwähnt, im JavaScript-Interpreter der Browser ausgeführt wird.
Entwickelt werden können die WebAssembly-Programme in etlichen Sprachen, angefangen bei C/C++ über Rust und Go bis hin zu C#. Und falls sich irgendwer hinsetzt und einen Compiler dafür schreibt, könnte man auch z. B. Basic C64 verwenden.

Aus Sicherheitssicht ist es aber egal, in welcher Sprache entwickelt wurde. Interessant sind dafür nur der Bytecode und dessen Ausführung. Und eigentlich sogar nur die Ausführung, denn der Bytecode stammt ja aus einer i. Allg. nicht vertrauenswürdigen Quelle, sodass man nicht weiß, ob er harmlos ist oder bösartig, oder vielleicht auch harmlos, aber kompromittiert. Sämtliche Schutzmaßnahmen müssen daher im Browser ergriffen werden.

Die Schutzmaßnahmen

Einige der Sprachen, die nach WebAssembly kompiliert werden können, erlauben den Zugriff auf beliebige Speicheradressen. Ein Angreifer könnte das nutzen, um im Browser gespeicherte sicherheitsrelevante Informationen wie z. B. Passwörter oder Authentifizierungstokens auszuspähen, sofern er deren Speicherort kennt. WebAssembly-Modulen werden daher separate Speicherbereiche zugewiesen.

Schutz des Speichers

Speicherzugriffe sind nur auf eine dedizierte Untermenge des Heaps der JavaScript VM möglich. Dieser spezielle Heap wird durch einen JavaScript ArrayBuffer realisiert. Dadurch gelten für den gesamten Speicher eines WebAssembly-Moduls die gleichen Beschränkungen wie für normale JavaScript-Objekte. Außerdem überwacht dadurch die Garbage Collection die Speichernutzung des Moduls und gibt den Speicher ggf. frei. Speicherlecks sind dadurch nur in den gleichen Grenzen wie bei normalen JavaScript-Programmen möglich.

Da der komplette Heap des WebAssembly-Moduls im ArrayBuffer steckt, weiß die JavaScript-Umgebung, wie groß der Heap des Moduls ist und wo genau er im JavaScript Heap liegt. Dadurch kann sie bei jedem Speicherzugriff des WebAssembly-Codes zum einen exakt nachprüfen, ob sich der Zugriff innerhalb des ArrayBuffers bewegt, und zum anderen unerlaubte Zugriffe unterbinden.

Unerlaubte Speicherzugriffe in die JavaScript VM oder gar in den Adressraum des Browserprozesses werden dadurch effektiv verhindert. Zwar verlangsamen diese Prüfungen die Ausführung des Programms etwas, aber ohne sie wäre die Ausführung von WebAssembly-Code viel zu gefährlich. Denn darin kann potenziell beliebiger Schadcode stecken.

Schutz des Execution-Stacks

Genauso gefährlich wie beliebige Zugriffe auf den Speicher sind Zugriffe auf den Execution-Stack. Der enthält außer den lokalen Variablen auch die Rücksprungadresse an die aufrufende Funktion. Gelingt es bösartigem Code, die Rücksprungadresse zu manipulieren, kann der Angreifer sie nutzen, um beliebigen Code auszuführen. WebAssembly verhindert einen Schreibzugriff auf den Execution-Stack, indem er außerhalb des Speichers des WebAssembly-Moduls gespeichert wird.

Vorsicht bei Sprüngen

Auch Befehle, die an andere Stellen im Code springen, sind generell gefährlich. WebAssembly springt nur bei Funktionsaufrufen Speicheradressen an. Die werden teilweise erst dynamisch zur Laufzeit berechnet. Um Manipulationen zu verhindern, kommen dabei Tabellen zum Einsatz. Statt die Zieladresse direkt im call-Befehl zu speichern, verwenden call-Befehle zwei Parameter: Einen Index in einer Tabelle und eine Funktionssignatur. Der Index zeigt in eine Tabelle mit Funktions-Pointern. Die wird genau wie der Execution-Stack außerhalb des WebAssembly-Moduls gespeichert, sodass ein Überschreiben durch das WebAssembly-Modul nicht möglich ist.

Bevor die WebAssembly-Laufzeitumgebung einen call-Befehl ausführt, prüft sie, ob die an den call-Befehl übergebene Funktionssignatur mit dem in der Tabelle am angegebenen Index gespeicherten Wert übereinstimmt. Nur wenn die beiden Signaturen übereinstimmen, wird die Funktion an der in der Tabelle gespeicherten Adresse aufgerufen. Gibt es unter dem Index keinen Eintrag in der Tabelle oder stimmen die beiden Signaturen nicht überein, wird die Ausführung des WebAssembly-Moduls sofort gestoppt.

Die beiden Parameter müssen nicht zwingend statisch gespeichert sein, sie können auch erst zur Laufzeit dynamisch generiert werden. Dadurch können z. B. Aufrufe an virtuelle Methoden in C++ oder Traits-Implementierungen in Rust realisiert werden.

WebAssembly ist fast immer deterministisch

Abgesehen von wenigen Ausnahmen erfolgt die Ausführung der WebAssembly-Programme generell deterministisch. Eine nichtdeterministische Ausführung kann nur in wenigen, wohldefinierten Fällen auftreten, in denen die Implementierung eine aus einer limitierten Menge möglicher Verhaltensweisen wählt. Außerdem sind die Effekte einer nichtdeterministischen Ausführung immer nur lokal.

Ein nichtdeterministisches Verhalten tritt z. B. auf, wenn WebAssembly um neue Features erweitert wird und die verschiedenen Implementierungen die Features unterschiedlich unterstützen. Zwar kann über has_feature die Unterstützung abgefragt werden, trotzdem unterscheiden sich die Ausführungen auf den verschiedenen Implementierungen voneinander. Auch wenn die umgebungsabhängigen Ressourcenlimits erreicht werden, kann es zu einem nichtdeterministischen Verhalten kommen, z. B. wenn Speicherreservierungen fehlschlagen oder der Stack des Programms voll ist.

Sichere Entwicklung (fast) garantiert

Das Design von WebAssembly unterstützt die Entwicklung sicherer Programme, indem auf gefährliche Features verzichtet wurde, während gleichzeitig die Kompatibilität zu in C/C++ geschriebenen Programmen erhalten blieb.

Funktionen

Die WebAssembly-Module müssen alle zugänglichen Funktionen und die zugehörigen Datentypen beim Laden deklarieren. Und das auch dann, wenn dynamisch gelinkt wird. Dadurch ist es möglich, durch einen strukturierten Kontrollfluss die Integrität des Kontrollflusses (Control-Flow Integrity, CFI) zu erzwingen. Da kompilierter Code unveränderlich und während der Laufzeit nicht beobachtbar ist, kann der Kontrollfluss der WebAssembly-Programme nicht manipuliert werden, Hijacking-Angriffe sind also nicht möglich.

Wie zuvor bereits erwähnt, müssen Funktionsaufrufe den gültigen Index der gewünschten Funktion in der Funktionstabelle (Function Index Space) oder Tabellentabelle (Table Index Space) enthalten. Bei indirekten Funktionsaufrufen wird vor der Ausführung die Signatur der Funktion geprüft. Der außerhalb des Modulspeichers abgelegte Stack ist vor Pufferüberlaufangriffen sicher. Branches (br, br_if, br_table) müssen zu gültigen Zielen in der aufrufenden Funktion führen.

Variablen

C/C++-Variablen können in WebAssembly in Abhängigkeit von ihrem Gültigkeitsbereich (Scope) auf zwei unterschiedliche Primitive reduziert werden. Lokale Variablen mit festem Gültigkeitsbereich und globale Variablen werden als Werte mit festem Typ repräsentiert, auf die über einen Index zugegriffen wird. Die lokalen Variablen werden mit null initialisiert und im geschützten Call-Stack gespeichert, die globalen Variablen befinden sich im globalen Index Space und können von externen Modulen importiert werden.

Lokale Variablen mit unklarem statischem Gültigkeitsbereich werden beim Kompilieren in einem separaten Stack im dem Programm zugänglichen linearen Speicher gespeichert. Dazu gehören z. B. Variablen, die vom address-of-Operator verwendet werden oder die den Type struct haben und als „Returned by Value“ zurückgegeben werden. Dieser Stack ist ein isolierter Speicherbereich mit fester Maximalgröße, der per Default mit null initialisiert wird.

Traps

Traps werden verwendet, um ggf. die Ausführung sofort beenden zu können und unnormales Verhalten an die Laufzeitumgebung zu melden. Im Browser werden dazu JavaScript Exceptions verwendet.

Traps können z. B. ausgelöst werden, wenn in irgendeinem Index Space ein ungültiger Index spezifiziert, ein indirekter Funktionsaufruf mit falscher Signatur durchgeführt oder im linearen Speicher auf verbotene Adressen zugegriffen wird.

Speicherschutz

Im Vergleich zu normalen C/C++-Programm verhindert WebAssembly verschiedene Klassen von Speicherfehlern. Z. B. sind die im Index Space gespeicherten lokalen und globalen Variablen vor Pufferüberläufen sicher, da sie eine feste Größe haben und über einen Index adressiert werden.

Im linearen Speicher abgelegte Daten können benachbarte Objekte überschreiben, da die Prüfung des Gültigkeitsbereichs mit der Genauigkeit des linearen Speicherbereichs erfolgt und nicht kontextsensitiv ist. Das Vorhandensein von Kontrollflussintegrität und geschützten Aufrufstacks verhindert jedoch das direkte Einschleusen von Code. Dadurch sind die sonst üblichen Mitigations wie Data Execution Prevention (DEP) und Stack Smashing Protection (SSP) in WebAssembly-Programmen nicht nötig.

Eine weitere übliche Klasse von Speicherfehlern entsteht durch unsichere Pointer-Nutzung und undefiniertes Verhalten. Ein klassisches Beispiel dafür ist die Dereferenzierung von Pointern in nicht reserviertem Speicher oder die Freigabe noch genutzten Speichers. In WebAssembly enthalten Funktionsaufrufe und Variablen mit festem statischem Gültigkeitsbereich keine Pointer. Verweise auf ungültige Indexe in irgendeinem Index Space lösen i. Allg. schon beim Laden einen Fehler aus, im schlimmsten Fall eine Trap zur Laufzeit. Bei Zugriffen auf den linearen Speicher werden die Grenzen auf Regionsebene geprüft, ggf. wird zur Laufzeit eine Trap ausgelöst. Diese Speicherbereiche sind vom internen Speicher isoliert (s. o.) und werden per Default auf null gesetzt, sofern sie nicht anderweitig initialisiert werden.

Einige andere Klassen von Fehlern werden von WebAssembly allerdings nicht verhindert. So kann zwar nicht direkt Code eingeschleust werden, aber das Hijacking des Kontrollflusses eines Moduls über Code Reuse Attacks gegen indirekte Funktionsaufrufe ist möglich. Konventionelle Angriffe über Return-oriented Programming (ROP) zum Missbrauch kurzer Codesequenzen (Gadgets) sind allerdings nicht möglich, da die Kontrollflussintegrität dafür sorgt, dass die Aufrufziele zur Ladezeit deklarierte, gültige Funktionen sind.

Auch Race Conditions wie z. B. „Time of Check to Time of Use“-(TOCTOU)-Schwachstellen und Seitenkanalangriffe sind möglich.

Kontrollflussintegrität

Die Wirksamkeit der Kontrollflussintegrität kann an ihrem Umfang gemessen werden. Generell muss der Kontrollfluss an drei Stellen geschützt werden:

  1. bei direkten Funktionsaufrufen,
  2. bei indirekten Funktionsaufrufen und
  3. bei Rücksprüngen.

Bei direkten Funktionsaufrufen wird der Kontrollfluss in WebAssembly durch die Verwendung des Indexwerts geschützt, bei Rücksprüngen durch den geschützten Call-Stack.

Die Prüfung der Funktionssignaturen bei indirekten Funktionsaufrufen zur Laufzeit garantiert eine grobkörnige, typbasierte Integritätssicherung. Der einzige noch mögliche Angriff bei indirekten Aufrufen ist, wie schon erwähnt, die Wiederverwendung von Code auf Funktionsebene.

Clang/LLVM enthält eine integrierte Implementierung einer feineren Kontrollflussintegrität. Diese wurde in Version 3.9+ mit dem neuen WebAssembly Backend auf WebAssembly portiert. Damit ist u. a. ein besserer Schutz vor Code-Reuse-Angriffen auf indirekte Funktionsaufrufe möglich.

„Early Adopters“: die Cyberkriminellen

Das sieht doch alles ganz gut bzw. sicher aus. Aber Sie ahnen es sicher schon: Es gibt da doch noch ein paar Haken – irgendwas ist ja immer.

Im Fall von WebAssembly sind das z. B. Crypto Miner. Die Cyberkriminellen scheinen mit die ersten gewesen zu sein, die die Vorteile von WebAssembly erkannt haben: Damit lassen sich Kryptowährungen im Browser deutlich schneller minen als mit JavaScript-Code.

Dementsprechend gibt es schon etliche entsprechende Schädlinge, die über infizierte Websites oder bösartige Werbung verbreitet werden. Das kann man natürlich nicht WebAssembly vorwerfen, der Vollständigkeit halber soll es aber nicht unerwähnt bleiben. Crypto Miner im Browser gab es auch schon vor der Einführung von WebAssembly, nur waren die dann eben deutlich langsamer, da sie „nur“ in JavaScript implementiert waren.

Generell kann fast jede JavaScript-basierte Schadsoftware nach WebAssembly portiert werden, aber das ist keine zusätzliche Gefahr. Ob der Schädling nun in JavaScript, WebAssembly oder „The next big Thing“ implementiert ist, ist egal. Die einzigen, die darüber jammern, sind die Antivirushersteller, denn die müssen nun in einem weiteren Datenformat nach Schadsoftware suchen. Und so eine Unverschämtheit: Das ist auch noch ein Binärformat, in dem sie nicht einfach nach Strings suchen können.

Ausbruch aus der Sandbox möglich

Alex Plaskett, Fabian Beterke und Georgi Geshev von den MWR Labs wollten mit einem Exploit für WebAssembly in Safari 11.0.3 unter macOS 10.13.3 am Pwn2Own-Wettbewerb 2018 teilnehmen. Daraus wurde leider nichts, da die von ihnen entdeckte und für den Angriff ausgenutzte Schwachstelle (CVE-2018-4121) unabhängig von ihnen auch von Natalie Silvanovich von Googles Project Zero entdeckt und an die Entwickler gemeldet wurde. Da Apple die Schwachstelle vor dem Wettbewerb kannte und dann auch geschlossen hatte, konnten Alex Plaskett, Fabian Beterke und Georgi Geshev ihren Exploit nicht mehr verwenden.

Er ist hier aber relevant, denn er beweist, dass trotz aller Schutzmaßnahmen ein Ausbruch aus der WebAssembly-Sandbox und die Kompromittierung des Systems möglich sind. Wie genau, haben die drei in einem Paper ausführlich beschrieben. Und das ist nicht die einzige Schwachstelle in den WebAssembly-Implementierungen.

WebAssembly als Einfallstor für Spectre-Angriffe

Die Spectre-Varianten 1 und 2 lassen sich über den Browser ausnutzen. Auch über WebAssembly. Dazu müssen die C/C++ Exploits nur nach WebAssembly kompiliert werden. Das ist unschön, da gerade bekannt wurde, dass die ganzen softwarebasierten Schutzmaßnahmen gegen Spectre-Angriffe weitgehend nutzlos sind. Von solchen Angriffen sind besonders Programme betroffen, die Daten aus nicht vertrauenswürdigen Quellen verarbeiten. Und bei mir und wahrscheinlich auch bei den meisten von Ihnen dürfte das am stärksten gefährdete Programm der Webbrowser sein – keine gute Kombination.

Was sagen die Sicherheitsforscher?

WebAssembly ist noch ziemlich neu, aber die Sicherheitsforscher haben schon damit begonnen, es auf Schwachstellen abzuklopfen. Siehe die gefundenen Schwachstellen und den für den Pwn2Own-Wettbewerb entwickelten Exploit. Auch auf den Sicherheitskonferenzen gab es erste Vorträge, z. B. gleich zwei auf der Black Hat USA 2018.

Vorsicht Gefahrenstelle!

Natalie Silvanovich von Googles Project Zero (die ja auch schon Schwachstellen in WebAssembly gefunden hat) hat „The Problems and Promise of WebAssembly“ vorgestellt. Dabei gibt es einen sowohl negativen als auch positiven Aspekt: Für die meisten Problemfelder konnte sie bereits tatsächliche Schwachstellen präsentieren, sie sind also keine theoretische, sondern eine konkrete Gefahr. Das ist natürlich erst mal schlecht. Andererseits aber zumindest bisher auch gut: Die Schwachstellen betreffen „nur“ Implementierungen von WebAssembly, nicht die Spezifikation. Die ist also (noch) sicher.
Konkret hat Natalie Silvanovich folgende Probleme angesprochen:

  • Das Parsen des Binärformats sowie dessen Laden in das Modul (3 Schwachstellen)
  • Die Speicherverwaltung (2 Schwachstellen)
  • Die Tabellen mit den Funktionen (2 Schwachstellen)
  • Die Initialisierung von Speicher und Elementen (1 Fehler, bisher keine Schwachstelle)
  • Der Export der WebAssembly-Funktionen (bisher keine Schwachstellen)
  • Probleme zur Laufzeit (bisher keine Schwachstellen)

Dass es Schwachstellen gibt, ist natürlich immer schlecht, aber ich denke, es hätte auch noch schlimmer kommen können. Die Anzahl der Schwachstellen ist doch sehr überschaubar. Außerdem sorgen die vorhandenen Sicherheitsfeatures dafür, dass die Wahrscheinlichkeit für Schwachstellen sinkt; jedenfalls in den WebAssembly-Programmen. Bei den Laufzeitumgebungen kommt es natürlich darauf an, wie sicher die Browserhersteller etc. sie implementieren.

Wie sich die Sicherheit von WebAssembly entwickelt, hängt nach Ansicht von Natalie Silvanovich von den zukünftigen Features ab. Und da sehe ich optimistisch in die Zukunft. Zum einen sind bereits weitere Sicherheitsfeatures angekündigt, zum anderen haben die WebAssembly-Entwickler schon bewiesen, dass sie Wert auf Sicherheit legen. Daher gehe ich davon aus, dass die nicht plötzlich anfangen, unsichere Features in die Spezifikation aufzunehmen. Vor allem, da die Entwicklung von WebAssembly von den Browserherstellern ausgeht, und die haben ein großes Interesse daran, dass die Browser sicher sind. Die werden kaum anfangen und die vorhandene Sicherheit durch unsichere WebAssembly-Features unterminieren.

WebAssembly = neue native Exploits im Browser

Kritischer sehen das Justin Engler und Tyler Lukasiewicz von der NCC Group WebAssembly, wie schon der Titel ihres Vortrags zeigt: „WebAssembly: A New World of Native Exploits on the Browser“. Die neuen „Nativen Exploits“ bestehen zum einen aus alten Exploits, die weiterhin funktionieren, und zum anderen aus neuen Exploits, die sich aus den Features von WebAssembly ergeben. Als Beispiele für alte Exploits nennen sie Angriffe auf Formatstringschwachstellen, Integer- und Pufferüberläufe. Einen Pufferüberlauf demonstrieren sie mit einem kleinen Beispiel. Weitere alte Exploits, die ihrer Ansicht nach wahrscheinlich funktionieren, sind Angriffe auf „Time of Check to Time of Use“-(TOCTOU-)Schwachstellen und Race Conditions sowie Timing- und Seitenkanalangriffe. Und auch Heap-basierte Schreibzugriffe können für Angriffe missbraucht werden.

Zum anderen gibt es neue Exploits. Da WebAssembly auf dem Umweg über JavaScript auf das DOM zugreifen kann, ist es möglich, über eine Pufferüberlaufschwachstelle einen DOM-basierten XSS-Angriff durchzuführen. Was auf den ersten Blick widersinnig erscheint, da sich über einen Pufferüberlauf sicher interessantere Sachen anstellen lassen, sieht auf den zweiten Blick doch schon etwas anders aus: Zum einen suchen die Funktionen zur Abwehr von XSS-Angriffen kaum im WebAssembly-Code danach, zum anderen kann über einen XSS-Angriff JavaScript und damit WebAssembly kontrolliert werden. Da lässt sich also durchaus Schaden mit anrichten, vor allem wenn man bedenkt, dass WebAssembly meist für aufwendige Webanwendungen verwendet wird.

Ein weiterer neuer Exploit sind Angriffe auf „Funktions-Pointer-Überläufe“. Die sind möglich, da die „Funktions-Pointer“ keine Pointer, sondern Indexe für die Funktionstabelle sind. Als Beispiele haben die beiden wieder einen XSS-Angriff durchgeführt und außerdem gezeigt, wie eine andere als die vorgesehene Funktion aufgerufen werden kann. Was je nach Funktion genauso gefährlich ist, wie die Ausführung beliebigen eingeschleusten Codes.

Verschlimmert wird das Ganze dadurch, dass die Angriffe auch mit Node funktionieren – und das führt zu einer Remote Code Execution auf dem Server.

Da sind noch einige Anpassungen und Erweiterungen bei den Schutzfunktionen nötig, aber die wurden zum Teil auch schon angekündigt. Entwicklern empfehlen die beiden Forscher Folgendes:

  • emscripten_run_script etc. zu vermeiden,
  • den Optimizer zu verwenden, wodurch nicht genutzte, automatisch hinzugefügte Funktionen entfernt und die Angriffsfläche für Angriffe auf den Kontrollfluss reduziert wird,
  • die Kontrollflussintegrität zu nutzen und vor allem
  • ihre C-Fehler zu beheben. Wobei ich in so einen Fall ja vorschlagen würde, die gar nicht erst zu machen.

Sicherheitstools

Es gibt auch schon erste Sicherheitstools für WebAssembly: Wasabi (kurz für „WebAssembly analysis using binary instrumentation“) ist ein am Software Lab der TU Darmstadt entwickeltes Framework zur dynamischen Analyse von WebAssembly-Programmen. Aron Szanto, Timothy Tamm und Artidoro Pagnoni von der Harvard University haben eine JavaScript-basierte VM für WebAssembly geschrieben, die Taint Tracking implementiert. Damit ist es möglich, den Fluss sensitiver Informationen zwischen den lokalen Variablen zu verfolgen und problematische Parameter zu erkennen.

Fazit

Insgesamt sieht es mit der Sicherheit von WebAssembly gut aus. Darum kann das Fazit auch kurz ausfallen: Es spricht nichts dagegen, WebAssembly zu nutzen. Als Entwickler ebenso wie als Benutzer.

Natürlich gibt es da noch einiges, was sich verbessern lässt, aber das gilt wohl für jede Software. Zumindest bisher wurden keine Schwachstellen in der Spezifikation gefunden (evtl. wurde auch nur nicht danach gesucht?), und die Anzahl der in den Implementierungen gefundenen Schwachstellen ist überschaubar. Und was Schwachstellen in den WebAssembly-Programmen betrifft: Interessiert sich wirklich irgendwer für die? Ich könnte mir vorstellen, dass die Cyberkriminellen sich darauf stürzen werden. Aber erst, wenn sie keine anderen Schwachstellen mehr finden, die sie ausnutzen können. Und bis dahin wird noch einige Zeit vergehen.

Und selbst wenn es irgendwann Angriffe auf WebAssembly-Programme geben wird: Wie viel Schaden können die Angreifer dann schon anrichten? Ist es nicht eher wahrscheinlich, dass sie den Clientcode der einen betroffenen Webanwendung zwar kompromittieren können, dann aber in der Sandbox festsitzen? Und Angriffe auf den Clientcode der Webanwendung sind auch heute schon möglich, so extrem sicher sind die JavaScript-Clients nun auch nicht. Aber haben Sie schon von großflächigen Angriffen gehört? Oder auch nur einzelnen? „In the Wild“ ist es da doch ziemlich ruhig. Und ich glaube kaum, dass sich das mit WebAssembly ändert.

Außerdem ist das Zukunftsmusik und bis es soweit ist, werden die Sicherheitsfunktionen bestimmt sehr viel ausgereifter sein. Und die Entwickler der WebAssembly-Programme können ja ihren Teil zur Sicherheit beitragen und die Schwachstellen in ihren Programmen korrigieren und keine neuen mehr entstehen lassen.

Links & Literatur

[1] Eilers, Carsten; Windows Developer 3.19: „CPU-Schwachstellen im Überblick – Sind Spectre und Meltdown nur die Spitze des Eisbergs?“

Carsten Eilers

Dipl.-Inform. Carsten Eilers war freier Berater und Coach für IT-Sicherheit und technischen Datenschutz sowie Autor einer Vielzahl von Artikeln für verschiedene Magazine und Onlinemedien.


Weitere Artikel zu diesem Thema