Mitigating Java Deserialization attacks from within the JVM Apostolos Giannakidis @cyberApostle BSides Luxembourg 20th October 2017 1
Who is BACKGROUND ◈ Security Architect at Waratek ◈ AppSec ◈ Runtime protection ◈ Vulnerability and exploit analysis ◈ R&D exploit mitigation ◈ MSc Computer Science 2
Key Takeaways ◈ Black/White listing is not an enterprise-scale solution ◈ Instrumentation Agents can be manipulated ◈ Runtime Virtualization offers privilege separation and memory isolation ◈ Runtime Privilege De-escalation safeguards application components and the JVM from API Abuse 3
Attack Vectors ● RPC/IPC ● Message Brokers ● Caching ● Tokens / Cookies ● RMI ● JMX ● JMS ● ... Why should I care? Attack Surface ● Oracle ● Red Hat ● Apache ● IBM ● Symantec ● Cisco ● Atlassian ● Adobe ● ... 4 Impact & Popularity ● Reliable attack ● Easy to exploit ● All software layers ● OWASP Top 10 2017 ● Oracle Java SE CPUs ● SF Muni breach ⬥ ~ 900 computers ⬥ ~$560k daily loss
Serialization 101 5
Deserialization of untrusted data What is the problem here? InputStream untrusted = request.getInputStream(); ObjectInputStream ois = new ObjectInputStream(untrusted); SomeObject deserialized = (SomeObject) ois.readObject(); 6
Deserialization of untrusted data What is the problem here? ◈ Any available class can be deserialized ◈ Deserializing untrusted data can result in malicious behavior ⬥ Arbitrary code execution ⬥ Denial of Service ⬥ Remote command execution ⬦ Malware / Ransomware infection InputStream untrusted = request.getInputStream(); ObjectInputStream ois = new ObjectInputStream(untrusted); SomeObject deserialized = (SomeObject) ois.readObject(); 7
How to solve the problem? ◈ Stop using deserialization ⬥ Requires significant refactoring ⬥ Requires architectural changes ⬥ Endpoints in other software layers? ⬥ Legacy software? ◈ Patch your software ⬥ Could break the application ⬥ “It is possible that some REST actions stop working” - CVE-2017-9805 ⬥ Oracle CPU October 2017 breaks backwards compatibility 8
Java Security Manager ◈ Custom Security Policy Filtering Class names ◈ Serialization Filtering (JEP-290) ◈ Custom Instrumentation Agents Runtime Virtualization ◈ Micro-compartmentalization ◈ Privilege De-escalation Existing Runtime Mitigation Techniques 9
Java Security Manager ◈ Difficult to configure it correctly ◈ Performance issues ◈ No protection against DoS attacks ◈ No protection against deferred deserialization attacks Critical Patch Update # vuls that can bypass the sandbox October 2017 18 July 2017 26 April 2017 8 January 2017 14 10
Discussion Time: Filtering class names Blacklisting Whitelisting 11
Blacklisting ● Requires profiling ● Never complete ● False sense of security ● Not possible if class is needed ● Can be bypassed Discussion Time: Filtering class names Whitelisting ● Requires profiling ● Difficult to do it right ● False positives if misconfigured ● No protection if class is needed ● No protection against Golden Gadgets ● Requires code reviews & testing 12
Whitelists are commonly mistreated 13http://activemq.apache.org/objectmessage.html
Maintaining lists is a shity job 14
Serialization Filtering (JEP-290) ◈ Introduced in Java 9 on January 2017 ⬥ Backported to Java 6, 7 and 8 ⬥ But not available in older JVM versions (e.g. 7u21) ◈ White / Black listing approach ◈ 3 types of filters ⬥ Global Filter, Custom Filters, Built-in Filters ◈ Graph and Stream Limits ⬥ Requires knowledge of graphs, JVM internals and details of all deployed code ⬥ Easy to get them wrong 15
Serialization Filtering problems !!!!! 16 https://stackoverflow.com/questions/42364744/how-to-ignore-java-io-serialization-logger-in-java
Serialization Filtering problems 17
Serialization Filtering problems 18
Instrumentation Agents ◈ Instrumentation API ◈ Black/ White listing approach ⬥ Global Filter ⬥ Custom Filters ◈ Known open source agents ⬥ NotSoSerial ⬥ Contrast-rO0 ⬥ more... 19
What is the problem with Instrumentation Agents? ? 20
What is the problem with Instrumentation Agents? ◈ Instrumentation API was not designed for Security From the Javadoc API: Instrumentation is the addition of byte-codes to methods for the purpose of gathering data. Since the changes are purely additive, these tools do not modify application state or behavior. Examples of such benign tools include monitoring agents, profilers, coverage analyzers, and event loggers. 21 https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html
Single Fault Domain ◈ Instr. agents and application share the same address space ◈ No separation of privileges ◈ Nothing prevents an app exploit to modify agent code/data ◈ Think of the browser/plugin, kernel/user-space paradigm ◈ Agents can be compromised by application attack vectors ◈ No protection against insider attacks ◈ Inappropriate for Cloud environments 22
Instrumentation Agents can turn into Double Agents ◈ Reporting & Blacklisting mode not suitable for production ◈ Configuration tampering at runtime ⬥ Backdoor deployment ⬥ Agent becomes DoS attack vector ◈ Protection can be disabled ◈ Log entries cannot be trusted 23
Demo PoC: Turn Contrast-rO0 against itself Setup ◈ Deploy the Contrast-rO0 instrumentation agent ◈ Use the default configuration file ◈ Run Tomcat with a vulnerable sample app Goal ◈ Tamper agent’s runtime configuration ◈ Remove blacklisted classes (aka add backdoors) 24 Source: https://github.com/maestros/fileuploadapp
Let’s study the attack carefully 25
Source: Chris Frohoff Marshalling Pickles AppSecCali 2015 ObjectInputStream.readObject() AnnotationInvocationHandler.readObject() Map(Proxy).entrySet() AnnotationInvocationHandler.invoke() LazyMap.get() ... InvokerTransformer.transform() Method.invoke() Runtime.exec() 26
Source: Chris Frohoff ysoserial LinkedHashSet.readObject() ... LinkedHashSet.add() ... Proxy(Templates).equals() ... ClassLoader.defineClass() Class.newInstance() ... Runtime.exec() 27
Let’s revisit the core of the problem ◈ The JVM is irrationally too permissive ◈ The JVM makes no effort to mitigate API Abuse attacks ◈ It is not even safeguarding its own invariants! ◈ All code and data can be accessible from any context ⬥ without a Security Manager 28
What do the standards suggest? CERT Secure Coding Standards ◈ SER08-J. Minimize privileges before deserializing from a privileged context ◈ SEC58-J. Deserialization methods should not perform potentially dangerous operations MITRE ◈ CWE-250: Execution with Unnecessary Privileges ⬥ [...] isolate the privileged code as much as possible from other code. Raise privileges as late as possible, and drop them as soon as possible. ◈ CWE-273: Improper Check for Dropped Privileges ⬥ Compartmentalize the system to have "safe" areas where trust boundaries can be unambiguously drawn. 29
Runtime Virtualization Deserialization Mitigation ◈ Runtime Virtualization ⬥ Places security controls in an isolated address space ⬥ Offers complete visibility of all executed instructions ◈ Runtime Micro-compartmentalization ⬥ Defines boundaries around operations ⬥ Controlled communication between compartments ◈ Runtime Privilege De-escalation ⬥ Allows only non-privileged operations after each boundary ⬥ Safeguards JVM’s state ⬥ Protects against API abuse cases 30
Conclusion ◈ Maintaining lists does not scale and is a burden ◈ Filtering classes can be too low level for AppSec teams ◈ Instrumentation Agents can become Double Secret Agents ◈ Do not use agent’s Reporting & Blacklist mode in production ◈ The runtime platform must: ⬥ be secure-by-default ⬥ safeguard the developer’s code from being abused 31
Thanks! Apostolos Giannakidis @cyberApostle BSides Luxembourg 20th October 2017 32
Discussion Time ◈ Bug hunting - Code reviewing deserialization gadgets ◈ Global Filters - Good or Bad? ◈ Attack detection using WAFs Apostolos Giannakidis @cyberApostle BSides Luxembourg 20th October 2017 33
public class LookupTable implements Serializable { private transient TableElement[] lookupTable; public LookupTable(int size) { int elements = Math.min(Math.max(4,size),32); lookupTable = new TableElement[elements]; } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { int numEntries = s.readInt(); lookupTable = new TableElement[numEntries]; } } Code Review #1 34
public final class TempFile implements Serializable { private String fileName; private void readObject(ObjectInputStream s) { s.defaultReadObject(); // read the field } public String toString() { return fileName != null ? fileName : ""; } private void finalize() { new File(fileName).delete(); } public File getTempFile() { return new File(fileName); } } Code Review #2 35
Know what you need to protect Audit Serializable classes Create Threat Model Re-evaluate Threat Model when class evolves Identify all deserialization end-points Add authentication in each end-point 36
Risk-based Management using lists ◈ Who should be responsible for their maintenance? ◈ Difficult to apply risk-based management ⬥ How should a class’s risk profile be assessed? ⬥ Developers understand code ⬥ AppSec teams understand operations ⬦ OS, File System, Network, Database, etc. 37
What is the problem with Global Filters? ◈ A Global Filter is ... Global (Process-wide) ◈ Applies to all deserialization endpoints ⬥ Even if the endpoint deserializes internal data ◈ Whitelist must include classes from all software layers ⬥ How do you know what classes are needed by each layer? ◈ Whitelisting with Global Filter increases risk exposure ⬥ Global Filter defines your deserialization attack surface 38
Check WAFs for False Positives HashMap<String, String> map = new HashMap<>(); map.put( “org.apache.commons.collections.functors.InvokerTransformer”, “calc.exe” ); FileOutputStream file = new FileOutputStream( "out.bin" ); ObjectOutputStream out = new ObjectOutputStream( file ); out.writeObject( map ); out.close(); 39
java.lang.reflect.Field configField = ClassLoader.getSystemClassLoader() .loadClass("com.contrastsecurity.rO0.RO0Agent").getField("config"); Object configObj = configField.get(null); Class<?> configClass = configObj.getClass(); java.lang.reflect.Field blacklistEnabledField = configClass.getDeclaredField("blacklistEnabled"); blacklistEnabledField.setAccessible(true); blacklistEnabledField.setBoolean(configObj, false); java.lang.reflect.Field blacklistField = configClass.getDeclaredField("blacklist"); blacklistField.setAccessible(true); blacklistField.set(configObj, null); 40
41 ● Runtime Application Self-Protection technology for Java applications built on top of the Oracle JVM ● A Java Container is a protected in-JVM container with built-in application security and quarantine controls ● The Java container separates apart the vulnerable JRE code from the low-level JVM ● Application security controls inserted between the Java Container and the JVM protect and quarantine the Java application Java Security via Runtime Virtual Containers

Mitigating Java Deserialization attacks from within the JVM (improved version)

  • 1.
    Mitigating Java Deserialization attacksfrom within the JVM Apostolos Giannakidis @cyberApostle BSides Luxembourg 20th October 2017 1
  • 2.
    Who is BACKGROUND ◈ SecurityArchitect at Waratek ◈ AppSec ◈ Runtime protection ◈ Vulnerability and exploit analysis ◈ R&D exploit mitigation ◈ MSc Computer Science 2
  • 3.
    Key Takeaways ◈ Black/Whitelisting is not an enterprise-scale solution ◈ Instrumentation Agents can be manipulated ◈ Runtime Virtualization offers privilege separation and memory isolation ◈ Runtime Privilege De-escalation safeguards application components and the JVM from API Abuse 3
  • 4.
    Attack Vectors ● RPC/IPC ●Message Brokers ● Caching ● Tokens / Cookies ● RMI ● JMX ● JMS ● ... Why should I care? Attack Surface ● Oracle ● Red Hat ● Apache ● IBM ● Symantec ● Cisco ● Atlassian ● Adobe ● ... 4 Impact & Popularity ● Reliable attack ● Easy to exploit ● All software layers ● OWASP Top 10 2017 ● Oracle Java SE CPUs ● SF Muni breach ⬥ ~ 900 computers ⬥ ~$560k daily loss
  • 5.
  • 6.
    Deserialization of untrusteddata What is the problem here? InputStream untrusted = request.getInputStream(); ObjectInputStream ois = new ObjectInputStream(untrusted); SomeObject deserialized = (SomeObject) ois.readObject(); 6
  • 7.
    Deserialization of untrusteddata What is the problem here? ◈ Any available class can be deserialized ◈ Deserializing untrusted data can result in malicious behavior ⬥ Arbitrary code execution ⬥ Denial of Service ⬥ Remote command execution ⬦ Malware / Ransomware infection InputStream untrusted = request.getInputStream(); ObjectInputStream ois = new ObjectInputStream(untrusted); SomeObject deserialized = (SomeObject) ois.readObject(); 7
  • 8.
    How to solvethe problem? ◈ Stop using deserialization ⬥ Requires significant refactoring ⬥ Requires architectural changes ⬥ Endpoints in other software layers? ⬥ Legacy software? ◈ Patch your software ⬥ Could break the application ⬥ “It is possible that some REST actions stop working” - CVE-2017-9805 ⬥ Oracle CPU October 2017 breaks backwards compatibility 8
  • 9.
    Java Security Manager ◈Custom Security Policy Filtering Class names ◈ Serialization Filtering (JEP-290) ◈ Custom Instrumentation Agents Runtime Virtualization ◈ Micro-compartmentalization ◈ Privilege De-escalation Existing Runtime Mitigation Techniques 9
  • 10.
    Java Security Manager ◈Difficult to configure it correctly ◈ Performance issues ◈ No protection against DoS attacks ◈ No protection against deferred deserialization attacks Critical Patch Update # vuls that can bypass the sandbox October 2017 18 July 2017 26 April 2017 8 January 2017 14 10
  • 11.
    Discussion Time: Filteringclass names Blacklisting Whitelisting 11
  • 12.
    Blacklisting ● Requires profiling ●Never complete ● False sense of security ● Not possible if class is needed ● Can be bypassed Discussion Time: Filtering class names Whitelisting ● Requires profiling ● Difficult to do it right ● False positives if misconfigured ● No protection if class is needed ● No protection against Golden Gadgets ● Requires code reviews & testing 12
  • 13.
    Whitelists are commonlymistreated 13http://activemq.apache.org/objectmessage.html
  • 14.
    Maintaining lists isa shity job 14
  • 15.
    Serialization Filtering (JEP-290) ◈Introduced in Java 9 on January 2017 ⬥ Backported to Java 6, 7 and 8 ⬥ But not available in older JVM versions (e.g. 7u21) ◈ White / Black listing approach ◈ 3 types of filters ⬥ Global Filter, Custom Filters, Built-in Filters ◈ Graph and Stream Limits ⬥ Requires knowledge of graphs, JVM internals and details of all deployed code ⬥ Easy to get them wrong 15
  • 16.
  • 17.
  • 18.
  • 19.
    Instrumentation Agents ◈ InstrumentationAPI ◈ Black/ White listing approach ⬥ Global Filter ⬥ Custom Filters ◈ Known open source agents ⬥ NotSoSerial ⬥ Contrast-rO0 ⬥ more... 19
  • 20.
    What is theproblem with Instrumentation Agents? ? 20
  • 21.
    What is theproblem with Instrumentation Agents? ◈ Instrumentation API was not designed for Security From the Javadoc API: Instrumentation is the addition of byte-codes to methods for the purpose of gathering data. Since the changes are purely additive, these tools do not modify application state or behavior. Examples of such benign tools include monitoring agents, profilers, coverage analyzers, and event loggers. 21 https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html
  • 22.
    Single Fault Domain ◈Instr. agents and application share the same address space ◈ No separation of privileges ◈ Nothing prevents an app exploit to modify agent code/data ◈ Think of the browser/plugin, kernel/user-space paradigm ◈ Agents can be compromised by application attack vectors ◈ No protection against insider attacks ◈ Inappropriate for Cloud environments 22
  • 23.
    Instrumentation Agents canturn into Double Agents ◈ Reporting & Blacklisting mode not suitable for production ◈ Configuration tampering at runtime ⬥ Backdoor deployment ⬥ Agent becomes DoS attack vector ◈ Protection can be disabled ◈ Log entries cannot be trusted 23
  • 24.
    Demo PoC: TurnContrast-rO0 against itself Setup ◈ Deploy the Contrast-rO0 instrumentation agent ◈ Use the default configuration file ◈ Run Tomcat with a vulnerable sample app Goal ◈ Tamper agent’s runtime configuration ◈ Remove blacklisted classes (aka add backdoors) 24 Source: https://github.com/maestros/fileuploadapp
  • 25.
    Let’s study theattack carefully 25
  • 26.
    Source: Chris Frohoff MarshallingPickles AppSecCali 2015 ObjectInputStream.readObject() AnnotationInvocationHandler.readObject() Map(Proxy).entrySet() AnnotationInvocationHandler.invoke() LazyMap.get() ... InvokerTransformer.transform() Method.invoke() Runtime.exec() 26
  • 27.
  • 28.
    Let’s revisit thecore of the problem ◈ The JVM is irrationally too permissive ◈ The JVM makes no effort to mitigate API Abuse attacks ◈ It is not even safeguarding its own invariants! ◈ All code and data can be accessible from any context ⬥ without a Security Manager 28
  • 29.
    What do thestandards suggest? CERT Secure Coding Standards ◈ SER08-J. Minimize privileges before deserializing from a privileged context ◈ SEC58-J. Deserialization methods should not perform potentially dangerous operations MITRE ◈ CWE-250: Execution with Unnecessary Privileges ⬥ [...] isolate the privileged code as much as possible from other code. Raise privileges as late as possible, and drop them as soon as possible. ◈ CWE-273: Improper Check for Dropped Privileges ⬥ Compartmentalize the system to have "safe" areas where trust boundaries can be unambiguously drawn. 29
  • 30.
    Runtime Virtualization DeserializationMitigation ◈ Runtime Virtualization ⬥ Places security controls in an isolated address space ⬥ Offers complete visibility of all executed instructions ◈ Runtime Micro-compartmentalization ⬥ Defines boundaries around operations ⬥ Controlled communication between compartments ◈ Runtime Privilege De-escalation ⬥ Allows only non-privileged operations after each boundary ⬥ Safeguards JVM’s state ⬥ Protects against API abuse cases 30
  • 31.
    Conclusion ◈ Maintaining listsdoes not scale and is a burden ◈ Filtering classes can be too low level for AppSec teams ◈ Instrumentation Agents can become Double Secret Agents ◈ Do not use agent’s Reporting & Blacklist mode in production ◈ The runtime platform must: ⬥ be secure-by-default ⬥ safeguard the developer’s code from being abused 31
  • 32.
  • 33.
    Discussion Time ◈ Bughunting - Code reviewing deserialization gadgets ◈ Global Filters - Good or Bad? ◈ Attack detection using WAFs Apostolos Giannakidis @cyberApostle BSides Luxembourg 20th October 2017 33
  • 34.
    public class LookupTableimplements Serializable { private transient TableElement[] lookupTable; public LookupTable(int size) { int elements = Math.min(Math.max(4,size),32); lookupTable = new TableElement[elements]; } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { int numEntries = s.readInt(); lookupTable = new TableElement[numEntries]; } } Code Review #1 34
  • 35.
    public final classTempFile implements Serializable { private String fileName; private void readObject(ObjectInputStream s) { s.defaultReadObject(); // read the field } public String toString() { return fileName != null ? fileName : ""; } private void finalize() { new File(fileName).delete(); } public File getTempFile() { return new File(fileName); } } Code Review #2 35
  • 36.
    Know what youneed to protect Audit Serializable classes Create Threat Model Re-evaluate Threat Model when class evolves Identify all deserialization end-points Add authentication in each end-point 36
  • 37.
    Risk-based Management usinglists ◈ Who should be responsible for their maintenance? ◈ Difficult to apply risk-based management ⬥ How should a class’s risk profile be assessed? ⬥ Developers understand code ⬥ AppSec teams understand operations ⬦ OS, File System, Network, Database, etc. 37
  • 38.
    What is theproblem with Global Filters? ◈ A Global Filter is ... Global (Process-wide) ◈ Applies to all deserialization endpoints ⬥ Even if the endpoint deserializes internal data ◈ Whitelist must include classes from all software layers ⬥ How do you know what classes are needed by each layer? ◈ Whitelisting with Global Filter increases risk exposure ⬥ Global Filter defines your deserialization attack surface 38
  • 39.
    Check WAFs forFalse Positives HashMap<String, String> map = new HashMap<>(); map.put( “org.apache.commons.collections.functors.InvokerTransformer”, “calc.exe” ); FileOutputStream file = new FileOutputStream( "out.bin" ); ObjectOutputStream out = new ObjectOutputStream( file ); out.writeObject( map ); out.close(); 39
  • 40.
    java.lang.reflect.Field configField =ClassLoader.getSystemClassLoader() .loadClass("com.contrastsecurity.rO0.RO0Agent").getField("config"); Object configObj = configField.get(null); Class<?> configClass = configObj.getClass(); java.lang.reflect.Field blacklistEnabledField = configClass.getDeclaredField("blacklistEnabled"); blacklistEnabledField.setAccessible(true); blacklistEnabledField.setBoolean(configObj, false); java.lang.reflect.Field blacklistField = configClass.getDeclaredField("blacklist"); blacklistField.setAccessible(true); blacklistField.set(configObj, null); 40
  • 41.
    41 ● Runtime ApplicationSelf-Protection technology for Java applications built on top of the Oracle JVM ● A Java Container is a protected in-JVM container with built-in application security and quarantine controls ● The Java container separates apart the vulnerable JRE code from the low-level JVM ● Application security controls inserted between the Java Container and the JVM protect and quarantine the Java application Java Security via Runtime Virtual Containers