© Swill Klitch/Shutterstock.com
Deserialisierungsschwachstellen im Java-Programmcode

Schutzmechanismen gegen Java-Deserialisierungs-Exploits


In diesem Teil unserer Artikelserie zu Deserialisierungsschwachstellen in Java sehen wir uns an, welche Schutzmechanismen existieren, um erste Maßnahmen vor dem Eintreffen eines geeigneten Patches zu treffen. Letztlich geht es um die Frage, wie man das Erstellen von Gadget Chains verhindern oder gleich ganz auf das Serialisierungs-API verzichten kann.

Das Java-Serialisierungs-API [1] erlaubt durch Deserialisierung die Umwandlung (Serialisierung) eines Java-Objektes in einen Bytestrom und andersherum. Wie ich bereits im Java Magazin 11.20 [2] dargestellt habe, erlaubt der Deserialisierungsmechanismus, ein Objekt beliebigen Typs und dessen Zustand zu rekonstruieren, das das Serializable-Interface implementiert und sich im Klassenpfad der Applikation befindet. Bei der besprochenen Schwachstelle nutzt der Angreifer dies aus, um eine Gadget Chain, also eine Kette von Objektausführungen, zu erzeugen. Das dient dazu, eigenen Programmcode in der fremden Anwendung zur Ausführung zu bringen. Die sinnvollste Art dieser Schwachstelle entgegenzuwirken, ist sicherlich, den Programmcode der Klassen derart zu ändern, dass keine Gadget Chain mehr gebaut werden kann, oder am besten ganz auf das native Serialisierungs-API zu verzichten.

Anfang 2013 veröffentlichte Pierre Ernst in seinem Paper [3] den technischen Ansatz zum Schutz vor Deserialisierungsangriffen, die heute in modernen Sicherheitsmechanismen Anwendung finden. Hierzu betrachtet Ernst den Bytestrom, der durch die Serialisierung erzeugt wird. In Ausgabe 11.20 des Java Magazins [2] wurde bereits gezeigt, wie ein Objekt der Klasse ShoppingBasket (Listing 1) serialisiert wird. Wie ein so serialisiertes Objekt im Hex-Editor aussieht, zeigt Listing 2.

Listing 1: ShoppingBasket-Klasse

import java.io.*; class ShoppingBasket implements Serializable { String artikel; // (1) int anzahl; // (2) int preis; // (3)  // ...

Listing 2

00000000: aced 0005 7372 000e 5368 6f70 7069 6e67 ....sr..Shopping 00000010: 4261 736b 6574 a061 7c96 fd20 4090 0200 Basket.a|.. @... 00000020: 0349 0006 616e 7a61 686c 4900 0570 7265 .I..anzahlI..pre 00000030: 6973 4c00 0761 7274 696b 656c 7400 124c isL..artikelt..L 00000040: 6a61 7661 2f6c 616e 672f 5374 7269 6e67 java/lang/String 00000050: 3b78 7000 0000 6400 0003 e874 0009 6950 ;xp...d....t..iP 00000060: 686f 6e65 2053 45 hone SE

Nach der Java Object Serialization Specification [4] werden die Datentypen und Variablenwerte im Bytestrom hinterlegt. Vor den Objektinhalten steht zusätzlich der Klassenname des serialisierten Objekts (in diesem Fall ShoppingBasket). Bei der Deserialisierung wird als erster Schritt dieser Klassenname aus den serialisierten Daten ausgelesen. Ernst erkannte, dass es einem Entwickler nach dem Serialisierungs-API [1] möglich ist, diesen Schritt durch das Überschreiben der resolveClass()-Methode, ähnlich wie in Listing 3 dargestellt wird, selbst zu implementieren und dort eine Eingabevalidierung durchzuführen. Letzteres nennt man „look-ahead class validation“.

Listing 3

import java.io.IOException; import java.io.InputStream; import java.io.InvalidClassException; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; public class LookAheadObjectInputStream extends ObjectInputStream { public LookAheadObjectInputStream(InputStream inputStream) throws IOException { super(inputStream); } @Override protected Class<?> resolveClass (ObjectStreamClass desc) throws IOException, ClassNotFoundException { if ( !desc.getName().equals(Bicycle.class) ) { throw new InvalidClassException("Unauthorized deserialisization Attack! With ", desc.getName()); } return super.resolveClass(desc); }

Die in Listing 3 dargestellte resolveClass()-Methode fungiert als ein Whitelist-Filter: Der Klassenname aus den serialisierten Date...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang