THE DESERIALKILLER
SICHERHEITSPROBLEME BEIMSERIALISIEREN UND DESERIALISIEREN
, Dr. Stefan Schlott BeOne Stuttgart GmbH
ABOUT.TXTStefan Schlott, BeOne Stuttgart GmbH
JavaEntwickler, ScalaEnthusiast, LinuxJünger
Seit jeher begeistert für Security und Privacy
WAS WAR PASSIERT
TO THE CRIME SCENE!
EINORDNUNG
OWASP KATEGORISIERUNG API Abuse Authentication Vulnerability Authorization Vulnerability Availability Vulnerability
Code Permission Vulnerability Code Quality Vulnerability Configuration Vulnerability
Cryptographic Vulnerability Encoding Vulnerability Environmental Vulnerability Error
Handling Vulnerability General Logic Error Vulnerability Input ValidationVulnerability Logging and Auditing Vulnerability Password Management Vulnerability
Path Vulnerability Protocol Errors Range and Type Error Vulnerability Sensitive Data
Protection Vulnerability Session Management Vulnerability Synchronization and Timing
Vulnerability Unsafe Mobile Code Use of Dangerous API
SQL INJECTIONFehlende InputValidierung: SQLStatement wird direkt
zusammengebaut
name = … // (direkt aus dem Webformular)result = SQL.exec("SELECT * FROM Students WHERE NAME='" + name + "';");
SELECT * FROM Students WHERE NAME='Robert';DROP TABLE Students;';
PERSISTENT CROSSSITE SCRIPTINGFehlende InputValidierung…
PERSISTENT CROSSSITE SCRIPTING…führt zu JavaScriptAusführung im Browser
SERIALISIERTE DATENAuch hier: Vorsicht mit Daten aus unbekannter Quelle!
Unbekannt = Alles von außen ohne Authentisierung
CodeAusfühung? In Java?
JAVA SERIALISIERUNG
SERIALISIERUNGS101public static void serializeData(String filename) throws … ConferenceSlot data = new ConferenceSlot("The DeSerial 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 WANDELTOBJEKT 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 LESENKlasse bestimmen
Instanz erzeugen: ZeroArgsConstructor der ersten nichtserialisierbaren 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 DEMO
„GADGET“ KONSTRUIERENZiel: Programm ausführen
Annahme: GroovyBibliothek im Klassenpfad
Idee: GroovyStrings haben eine Methode execute, welche denString als Kommando ausführt
Methode als GroovyClosure 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 beim Zusammenbauenausgeführt.
Also: Platzhalter setzen und string per Reflection setzen.
DESERIALISIERUNG1. BadAttributeValueExpException wird gelesen, derenreadObjectMethode gerufen
2. Diese liest string, diese liest payloadClosure(Standardmechanismus)
3. BadAttributeValueExpException::readObject rufttoString von string
4. GStringImpl::toString ruft payloadClosure.call()
VIELFÄLTIGE ANWENDUNGRMI
JMX
JMSNachrichten
JSFViewstate
ObjectCaches, z.B. (anwendungsspezifisch) memcached
…
Authentisierung hilft nicht zwingend!Beispiel: JMX
AUCH ANDERE SPRACHEN!
RUBYONRAILSMELTDOWN…als prominentes Beispiel
(analoges lässt sich mit Python, PHP, etc. darstellen)
YAML DESERIALIZATION PROBLEMRailsBug vom Januar 2013
(betroffen: Alles vor 3.2.11, 3.1.10, 3.0.19 und 2.3.15)
Problem: Mittels XMLMarkup konnte automatisch ein YAMLParserangestoßen werden:
<fool type='yaml'>…yaml goes here…</fool>
YAML: MEHR ALS NUR LESBARE DATENNicht (nur) strukturierte Daten, sondern vollständige Serialisierung!
Mit !klassenname Klasse instantiieren
Syntax Hashmap = Members belegen
Mit !klassenname [ p1, … ] Konstuktorparameter angeben
ANDERE SERIALISIERUNGSBIBLIOTHEKEN
YAMLProminente JavaBibliothek: SnakeYaml
YAML: Objektinstantiierungen, Konstuktorparameter
Kümmert sich nicht um Serializable
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. LogStatement) löst Exploit aus
Lösung für SnakeYaml: SafeConstructor limitiert auf BasistypenYaml yaml = new Yaml(new SafeConstructor());
Weitere Klassen können registriert werden
Unglücklicherweise nicht der Default!
XSTREAM„No mappings required. Most objects can be
serialized without need for specifyingmappings“
Kompatibel mit normaler JavaSerialisierung!
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.TransformingComparator"> <decorated class="org.apache.commons.collections4.comparators.ComparableComparator"/> <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
FAZIT
Die Bibliotheken müssen ihre Probleme fixen!
Problem nicht neu
Problem nicht Javatypisch
Problem nicht in Apache Commons, Groovy, etc.
Potentielle Problemquelle: Nicht authentisierte Daten
Potentielle Problemquelle:Jede generische SerialisierungsBibliothek
Beschränkung der verwendbaren Klassen
Aber: JavaSerialisierung: Kaum abzudichten
Bibliotheken mit sicheren Defaults verwenden
Twitter:
Dr. Stefan Schlotthttp://www.beonegroup.com/stefan.schlott@beonegroup.com
@_skyr
BILDQUELLEN (CC) BY Nick kenrick
(CC0) niekverlaan (CC) BYNCSA Michele Adami
(CC) BY _Gavroche_ (CC0) condesign
(CC) BYNC Randall Munroe (CC) BYNCSA Canada Science and Technology Museum
(CC0) Pexels (CC) BYNCSA 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 whackamole Not standard usage of standard library
Top Related