the worst case ... and will crash your JVM in the best. Spoiler Alert: Who has heard about the news (in 2015) about dangerous Java deserialization vulnerabilities? How many of you have checked and/or patched their systems in some way? Who thinks her/his systems are not affected?
for years by the security community • News around Apache Commons-Collections made the topic available to a broader audience in 2015 • Some inaccurate advice to protect your applications is making the rounds • In this talk we’ll demonstrate the weakness of this advice by … • … showing you new remote code execution risks • … showing you how attackers can bypass these • We’ll give advice how to spot this vulnerability and its gadgets during … • … code reviews (i.e. showing you what to look for) • … pentests (i.e. how to generically test for such issues) 4
as a byte stream that can be used to reconstruct the object graph to its original state –Only object data is serialized, not the code –The code sits on the Classpath of the deserializing end Object Graph Object Graph ACED 0005 …
have dangerous code: • Attacker controls member fields’ values of serialized object • Upon deserialization .readObject() / .readResolve() is invoked • Aside from the classic ones also lesser-known "magic methods" help: • .validateObject() as part of validation (which does not prevent attacks) • .readObjectNoData() upon deserialization conflicts • .finalize() as part of GC (even after errors) • Works also for Externalizable’s .readExternal()
exploits use multiple steps • Build a chain of gadgets consisting of • Classes commonly available in target’s ClassPath • Many already existing • Our research found some interesting new… • Just the class sitting on target’s ClassPath is enough • ...when application has a deserialization endpoint 24
serialization: • Attacker controls member fields of IH gadget, which has dangerous code • IH (as part of Dynamic Proxy) gets serialized by attacker as field on which an innocuous method is called from "magic method" (of class to deserialize) • Application steps upon deserialization: • "Magic Method" of "Trigger Gadget" calls innocuous method on an attacker controlled field • This call is intercepted by proxy (set by attacker as this field) and dispatched to IH • Other IH-like types exist aside from java.lang.reflect.InvocationHandler • javassist.util.proxy.MethodHandler (no requirement to implement interface) • org.jboss.weld.bean.proxy.MethodHandler 28
public final Object readObject(ObjectInputStream ois) throw Exception { ois.defaultReadObject(); comp.compare("foo", "bar"); } } Toy Example: Trigger Gadget 29 Attacker controls this field, so it can set it to anything implementing java.util.Comparator … anything, even a Proxy Proxy will intercept call to “compare()” and dispatch it to its Invocation Handler 29
• InvocationHandler • Upon method interception custom BeanShell code will be called • Almost any Java code can be included in the payload • In order to invoke the payload a trigger gadget is needed to dispatch the execution to the InvocationHandler invoke method 31
"Untrusted Java Deserialization", which means "Remote Code Execution" • Found as part of bug-bounty in December 2015 by Mark Litchfield (rewarded by PayPal with $ 15.000) • Independently found two days later by Michael Stepankin (still rewarded by PayPal with $ 5.000 even as duplicate) • Fixed within 48 hours by PayPal (respect!) http://artsploit.blogspot.de/2016/01/paypal-rce.html https://www.linkedin.com/pulse/my-50k-personal-challenge-results-mark-litchfield https://www.paypal-engineering.com/2016/01/21/lessons-learned-from-the-java-deserialization-bug/
server" payload with ysoserial • Base64 encode it (if required by endpoint) • Use as replacement for original Java deserialization value • i.e. hidden form field’s value in submit in PayPal scenario • ;-)
2011) • First public exploit: (by @pwntester in 2013) • Commons-fileupload (by Arun Babu Neelicattu in 2013) • Groovy (by cpnrodzc7 / @frohoff in 2015) • Commons-Collections (by @frohoff and @gebl in 2015) • Spring Beans (by @frohoff and @gebl in 2015) • Serial DoS (by Wouter Coekaerts in 2015) • SpringTx (by @zerothinking in 2016) • JDK7 (by @frohoff in 2016) • Beanutils (by @frohoff in 2016) • Hibernate, MyFaces, C3P0, net.sf.json, ROME (by M. Bechler in 2016) • Beanshell, Jython, lots of bypasses (by @pwntester and @cschneider4711 in 2016) • JDK7 Rhino (by @matthias_kaiser in 2016) • ... 44
classes in the JRE will highly increase attacker success ratio. • No dependencies required! • Golden JRE Gadgets known so far: • Rhino by Matthias Kaiser. Up to JRE 7u13 • AnnotationInvocationHandler I by Chris Frohoff. Up to JRE 7u21 • AnnotationInvocationHandler II by Alvaro Munoz. Up to JRE 8u20 • CORBA Stubs by Alexandr Mirosh and Alvaro Munoz. • Works on every JRE version, but requires a Security Manager to be installed 45
with expected types (i.e return valid types for the cast which fire later) If you can uninstall/restore the Security Manager or refresh the policy, attackers might be able to do it Mitigation Advice #2: AdHoc Security Manager
execution: • finalize() method • Play with expected types (i.e return valid types for the cast which fire later) If you can uninstall/restore the Security Manager or refresh the policy, attackers might be able to do it
bypass ad-hoc look-ahead ObjectInputStream blacklist protections: • During deserialization of the object graph, a new immaculate unprotected ObjectInputStream will be instantiated • Attacker can provide any arbitrary bytes for unsafe deserialization • Bypass does not work for cases where ObjectInputStream is instrumented 51 public class NestedProblems implements Serializable { private byte[] bytes … ; … private void readObject(ObjectInputStream in) throws … { ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); ois.readObject(); } }
Wouter Coekaerts • HashSet Billion-Laughs Style • jInfinity by Arshan Dabirsiaghi • Size-uninitialized StringBuilder may be abused by huge strings to allocate a large amount of growing character arrays • OIS-DOS by Tomáš Polešovský • Heap overflow when deserializing specially crafted nested ArrayLists, HashMaps or Object arrays • Hashtable collision • Uses an Integer overflow to force underlying array to be length 1 and so creating collisions when adding items with same hashCode • HashMap collision • Number of buckets is directly controllable by attacker • Official response: Won’t fix: Serialization should only be used in trusted environments 54
being deserialized contains a Java deserialization callback (eg: readObject), it will get called by XStream • Same gadgets can normally be used with XStream • More gadgets are available to attackers since XStream does not require Serializable interface to be implemented. • XStream implemented a blacklist/whitelist protection • Unfortunately developers are not fully aware and still use unprotected or only blacklisted XStream instances • Attackers can use Bypass gadgets to lunch pure Java deserialization attacks 57
When architecture permits it: • Use other formats instead of serialized objects: JSON, XML, etc. • But be aware of XML-based deserialization attacks (XStream, XmlDecoder, etc.) As second-best option: Use defensive deserialization with look-ahead OIS with a strict whitelist • Don’t rely on gadget-blacklisting alone! • You can build the whitelist with OpenSource agent SWAT ( Serial Whitelist Application Trainer: https://github.com/cschneider4711/SWAT ) • Prefer an agent-based instrumenting of ObjectInputStream towards LAOIS • Scan your own whitelisted code for potential gadgets • Still be aware of DoS scenarios 60
flexible mechanism to narrow the classes that can be deserialized from any class available to an application down to a context-appropriate set of classes. • Provide metrics to the filter for graph size and complexity during deserialization to validate normal graph behaviors. • Provide a mechanism for RMI-exported objects to validate the classes expected in invocations. • The filter mechanism must not require subclassing or modification to existing subclasses of ObjectInputStream. • Define a global filter that can be configured by properties or a configuration file. 65 Whitelist defensive deserialization Denial of Service mitigation Secure RMI Backwards compatible, Catch‘em all! Configurable
(untrusted) serialized data • Find calls to: • ObjectInputStream.readObject() • ObjectInputStream.readUnshared() • Where InputStream is attacker-controlled. For example: • May happen in library code like JMS, JMX, RMI, Queues, Brokers, Spring HTTPInvokers, etc. InputStream is = request.getInputStream(); ObjectInputStream ois = new ObjectInputStream(is); ois.readObject();
java.io.Serializable.readResolve() – java.io.ObjectInputValidation.validateObject() – java.lang.Object.finalize() – Serializable InvocationHandlers – … Finding Gadgets in a Haystack Look for interesting method calls … – java.lang.reflect.Method.invoke() – java.io.File() – java.io.ObjectInputStream() – java.net.URLClassLoader() – java.net.Socket() – java.net.URL() – javax.naming.Context.lookup() – … • Check your code for potential gadgets, which could be used in deserialization • "Gadget Space" is too big. Typical app-server based deployments have hundreds of JARs • SAST tools such as HPE Fortify SCA might help
carrying serialized Java objects: • Easy to spot due to magic bytes at the beginning: 0xAC 0xED … • Some web-apps might use Base64 to store serialized data in Cookies, etc.: rO0AB … • Be aware that compression could’ve been applied before Base64 • 0x1F8B 0x0800 … • H4sIA … • Tools • Use professional scanners (e.g. HPE WebInspect) for enterprise-level scans • Use free interception proxies (e.g. OWASP ZAP, Burp) to passively scan for Java serialization • Use network sniffers (e.g. Wireshark) for network traffic
• Identify your critical applications’ exposure to untrusted data that gets deserialized • For already reported vulnerable products, ensure to apply patches • Configure applications with whitelists where possible In the first few months following this presentation you should: • If possible switch the deserialization to other formats (JSON, etc.), or • Use defensive deserialization with a strict whitelist Within six months to one year you should: • Use DAST to actively scan for deserialization vulnerabilities as part of your process • Apply SAST techniques to search for attacker-helping gadgets • Extend this analysis also to non-critical applications 70