28C3: Eine Konferenz, viele neue Angriffe

Neues rund um die Websecurity
Kommentare

Entwickler Magazin

Der Artikel „28C3: Eine Konferenz, viele neue Angriffe“ von Carsten Eilers ist erstmalig erschienen im Entwickler Magazin 2.2012
Gleichwertige Teil-Strings
Einige Hash-Funktionen

Entwickler Magazin

Der Artikel „28C3: Eine Konferenz, viele neue Angriffe“ von Carsten Eilers ist erstmalig erschienen im Entwickler Magazin 2.2012

Gleichwertige Teil-Strings

Einige Hash-Funktionen haben die Eigenschaft, dass immer dann, wenn zwei Strings kollidieren, auch Eingaben, die diese Strings als Teil-String enthalten, kollidieren: Gilt hash(’string1′) = hash(’string2′) , dann gilt auch hash(‚prefixstring1postfix‘) = hash(‚prefixstring2postfix‘) . Ein Angreifer kann dieses Verhalten ausnutzen, um eine beliebige Anzahl an Kollisionen zu erzeugen.

„Meet-in-the-middle“-Angriffe

Gibt es in einer Hash-Funktion keine gleichwertigen Teil-Strings, sind auf den ersten Blick nur Brute-Force-Angriffe zur Suche nach Kollisionen möglich. Dazu wird ein Zielwert gewählt und danach solange der Hash-Wert zufälliger Strings mit fester Länge berechnet, bis sich der Zielwert als Hash-Wert ergibt. Für eine Hash-Funktion mit 32 Bit langen Hash-Werten beträgt die Wahrscheinlichkeit für das Treffen des Zielwerts 1/(232). Bei einem Meet-in-the-middle-Angriff wird versucht, mehr als einen Zielwert gleichzeitig zu finden. Kann die Hash-Funktion invertiert werden und ihr interner Status hat die gleiche Länge wie die Ausgabe, kann der String in zwei Teile, den Prefix und den Postfix, aufgespalten werden. Nun kann über alle möglichen Postfix-Strings iteriert und der Zwischenwert berechnet werden, aus dem sich ein bestimmter Hash-Wert ergibt. Die Strings und zugehörigen Zwischenwerte werden in einer Tabelle gespeichert, danach werden zufällige Prefix-Strings gebildet und mit dem Zwischenwert verglichen. Bei einer Übereinstimmung ergibt der komplette String aus Prefix und Postfix den gewünschten Hash-Wert. Durch das Aufspalten in der Mitte reduziert sich die Komplexität um die Quadratwurzel, die Wahrscheinlichkeit für einen Treffer liegt nun bei 1/(216). Mit dem Meet-in-the-middle-Angriff lassen sich Kollisionen also sehr viel schneller als mit einem Brute-Force-Angriff ermitteln.

Von der Schwachstelle zum Angriff

Bisher wissen wir, dass sich durch bestimmte Eingaben die Ausführungszeiten der Hash-Funktionen stark nach oben treiben lassen, und dass sich die benötigten Kollisionen mehr oder weniger effektiv berechnen lassen. Aber wie lässt sich das für einen DoS-Angriff nutzen? Hier kommt die Speicherung von POST-Daten durch die betroffenen Skriptsprachen und Plattformen zum Zuge: Sie werden in Hash-Tabellen gespeichert, sodass über entsprechende Eingaben ein DoS durch Verbrauch sämtlicher Rechenleistung ausgelöst werden kann. In der Exploit Database und auch auf anderen Websites wurden bereits erste Exploits zum Ausnutzen der Schwachstelle veröffentlicht.

Betroffene Sprachen und Plattformen

PHP 5 nutzt die für gleichwertige Teil-Strings anfällige Hash-Funktion DJBX33A und speichert die POST-Daten in der Hash-Tabelle $_POST. Die Optionen max_input_time und max_execution_time schränken die Möglichkeiten eines Angreifers ein, können einen Angriff aber nicht verhindern. Ein Angreifer kann mit 70 bis 100 Kilobit pro Sekunde einen i7-Core-Prozessor konstant auslasten, mit einer Gigabitleitung können rund 10 000 i7-Core-Prozessoren ausgelastet werden.

ASP.NET speichert POST-Daten im Objekt Request.Form und verwendet die für Meet-in-the-middle-Angriffe anfällige Hash-Funktion DJBX33X. Der IIS-Webserver beschränkt die CPU-Zeit, das kann einen Angriff aber nicht verhindern. Ein Angreifer kann mit etwa 30 Kilobit pro Sekunde einen Core2-Prozessor auslasten, mit einer Gigabitleitung können 30 000 Core2-Prozessoren ausgelastet werden.

Java enthält die Klassen HashMap und Hashtable, die eine für gleichwertige Teil-Strings anfällige Variante der Hash-Funktion DJBX33A verwenden. Java speichert die Hash-Werte in einem Cache, wenn sie ungleich 0 sind. Für einen Angriff sind also besonders die Werte interessant, die einen Hash-Wert von 0 ergeben, da die Hash-Funktion dann jedes Mal neu berechnet werden muss.

Die untersuchten Plattformen Tomcat, Geronimo, Jetty und GlassFish speichern POST-Daten in HashMap– oder Hashtable-Objekten, wobei die maximale Größe der Daten schwankt. Im Fall von Tomcat kann ein Angreifer mit sechs Kilobit pro Sekunde einen i7-Core-Prozessor auslasten, mit einer Gigabitleitung können 100 000 i7-Core-Prozessoren ausgelastet werden.

Python verwendet eine mit der Funktion DJBX33X vergleichbare Hash-Funktion, die für Meet-in-the-middle-Angriffe anfällig ist. Die Funktion arbeitet auf Registergröße, sodass die Ergebnisse für 32- und 64-Bit-Rechner unterschiedlich ausfallen. Für beide Versionen lassen sich Kollisionen berechnen, für die 64-Bit-Version sind die sich ergebenden Strings für einen praktischen Angriff zu groß.

Das verbreitetste Framework Plone akzeptiert ein Megabyte POST-Daten. Ein Angreifer kann mit 20 Kilobit pro Sekunde einen Core2-Prozessor auslasten, mit einer Gigabitleitung etwa 50 000 Core2-Prozessoren.

Ruby verwendet je nach Implementierung und Version unterschiedliche Hash-Funktionen. Die Hash-Funktion in CRuby 1.9 verwendet seit 2008 Randomization, das heißt, es wird ein zufälliger Wert in die Hash-Berechnung einbezogen und ist nicht angreifbar. Die Hash-Funktion in CRuby 1.8 ist mit DJBX33A vergleichbar, aufgrund anderer interner Parameter ist jedoch kein Angriff über gleichwertige Teil-Strings möglich, sondern nur ein Meet-in-the-middle-Angriff. JRuby 1.8 und 1.9 verwenden die gleiche Funktion wie CRuby 1.8, Rubinius verwendet eine andere Hash-Funktion, die aber ebenfalls keine Randomization verwendet. Ruby-Frameworks verarbeiten typischerweise zwei Megabyte POST-Daten, ein Angreifer kann in CRuby 1.8 mit Rack einen i7-Core-Prozessor mit 720 Bit pro Sekunde auslasten, mit einer Gigabitleitung rund 1 000 000 (eine Million!) i7-Core-Prozessoren.

Die Hash-Funktion von Googles JavaScript-Implementierung v8> ist nicht mit den anderen Hash-Funktionen vergleichbar, aber ebenfalls für Meet-in-the-middle-Angriffe anfällig. Node.js verwendet v8 zur Ausführung JavaScript-basierter Webanwendungen und speichert POST-Daten in einer Hash-Tabelle. Da deren Größe nicht beschränkt ist, haben Alexander Klink und Julian Wälde auf Untersuchungen der Effektivität und Effizienz von Angriffen verzichtet.

Jede Webanwendung, die eine dieser Technologien verwendet und POST Requests verarbeitet, kann über präparierte POST Requests angegriffen werden. Ein Angreifer kann diese sowohl selbst an die Webanwendung schicken als auch zum Beispiel über XSS in eine Webanwendung einschleusen und dann darüber eine andere Webanwendung angreifen. Wie es außerhalb des Webs aussieht, ist noch weitgehend offen. Prinzipiell sind überall, wo von einem Angreifer manipulierbare Daten von Hash-Funktionen verarbeitet werden, entsprechende Angriffe möglich.

Tabelle 1: Effektivität der DoS-Angriffe

Ziel CPU für 1 CPU werden … benötigt 1 Gbit/s reichen für … CPUs
PHP 5 i7 Core 70 bis100 kbit/s ca. 10 000
ASP.NET Core2 ca. 30 kbit/s ca. 30 000
Java/Tomcat i7 Core ca. 6 kbit/s ca. 100 000
Python/Plone Core2 ca. 20 kbit/s ca. 50 000
CRuby 1.8/Rack i7 Core ca. 720 bit/s ca. 1 000 000
Patches und Updates

Für die Open-Source-Lösungen hat das oCERT die Koordinierung übernommen [5], die Schwachstelle in ASP.NET wurde Microsoft über das US-CERT gemeldet. Beim Beheben der Schwachstelle gehen die Ergebnisse auseinander:

  • In PHP wurde sie im Subversion Repository durch Einführen der neuen Direktive max_input_vars behoben, die die maximal zulässige Anzahl von POST-, GET- und COOKIE-Parametern beschränkt [6]. Der Patch ist in Version 5.3.9 und 5.4.0 RC enthalten [7].
  • Microsoft hat am 29.12. einen außerplanmäßigen Patch Day zum Beheben der Schwachstelle in ASP.NET eingelegt [8]. Auch hier wurde die Anzahl zulässiger Eingabeparameter begrenzt, in einem zukünftigen Update werden die Hash-Funktionen überarbeitet.
  • Für Java wird es keinen Patch geben, für GlassFish wird ein Update vorbereitet. Für Tomcat gibt es Updates (5.5.35, 6.0.35, 7.0.23), die die Anzahl der Request-Parameter über eine Konfigurationsoption beschränken.
  • Für Python/Plone ist ein Patch in Arbeit.
  • Für Ruby gibt es neue Versionen von CRuby und JRuby mit neuen, um einen Zufallsfaktor erweiterten Hash-Funktionen (CRuby 1.8.7-p357, JRuby 1.6.5.1). Außerdem gibt es neue Versionen der Rack Middleware (1.1.3, 1.2.5, 1.3.6, 1.4.0).
  • Zu Geronimo, Jetty, Rubinius und v8/node.js gibt es keine aktuellen Informationen.
Workarounds

Für Sprachen und Umgebungen, für die es keinen Patch gibt, stehen eine Reihe von Workarounds zur Verfügung:

  1. Beschränkung der CPU-Zeit für die Bearbeitung eines Requests, z. B. in PHP über die Option max_input_time
  2. Beschränkung der Größe eines POST Requests
  3. Beschränkung der Anzahl der Parameter, z. B. in der Suhosin-Version von PHP über die Optionen suhosin.post.max_vars und suhosin.request.max_vars
  4. Ausfiltern bösartiger Requests mit einer Web Application Firewall oder einem Intrusion-Prevention-System. Microsoft hat im Security Research & Defense Blog Snort-Regeln zum Erkennen eines Angriffs auf ASP.NET veröffentlicht [9].

Kommen wir zum nächsten Thema, dem nächsten, neuen Angriff.

Rootkits für Webclients

Artur Janc hat einen Vortrag mit dem Titel „Rootkits in your Web Application“ [10] gehalten. Rootkits in Webanwendungen, das klingt erst einmal merkwürdig, und der Untertitel trägt nicht gerade zur Aufklärung bei: „Achieving a permanent stealthy Compromise of User Accounts with XSS and JS Injection Attacks“. Aber nehmen wir diese Aussagen mal auseinander: Wie kann man Benutzerkonten kompromittieren? Im klassischen Fall passiert das, indem der Angreifer sich Zugriff auf das Benutzerkonto auf dem Webserver beziehungsweise in der Webanwendung verschafft, zum Beispiel indem er das Passwort abphisht oder einen gültigen Session-Cookie ausspäht. Es gibt aber, vor allem in Zeiten des Web 2.0 und von HTML5, einen weiteren Ansatzpunkt: den Client der Webanwendung. Bekommt ein Angreifer die Kontrolle über den Client eines Benutzers, kann er danach in dessen Namen mit der Webanwendung interagieren. Er muss also gar nicht mehr die Webanwendung selbst angreifen, es reicht, wenn er die Kontrolle über einen Client übernimmt. Und was ist ein Rootkit? Ein Rootkit wird von Angreifern eingesetzt, um nach einer erfolgreichen Kompromittierung die Kontrolle über den angegriffenen Rechner zu erhalten und möglichst unentdeckt zu bleiben [11]. Das funktioniert natürlich sinngemäß auch im Rahmen einer Webanwendung, und zwar sowohl auf dem Server als auch auf dem Client. Und genau so geht auch Artur Janc vor: Er greift nicht die Webanwendung selbst, sondern deren Client an. Dabei geht er davon aus, dass der Angreifer es schafft, einem Benutzer JavaScript-Schadcode unterzuschieben, zum Beispiel wenn ein Benutzer eine präparierte Webseite aufruft, die den Schadcode enthält.

Resident XSS

Von diesem Schadcode wird dann weiterer Schadcode in den Client der Webanwendung eingeschleust, die das eigentliche Ziel des Angriffs ist. Dazu kann der Schadcode zum Beispiel einen neuen Tab zur angegriffenen Webanwendung öffnen, mit dem der Benutzer dann arbeitet. Artur Janc bezeichnet das als „Resident XSS“ und hat mehrere Möglichkeiten für dessen Einschleusen beschrieben.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -