This article was originally published on the Red Hat Customer Portal. The information may no longer be current.
Recent research by Chris Frohoff and Gabriel Lawrence has exposed gadget chains in various libraries that allow code to be executed during object deserialization in Java. They've done some excellent research, including publishing some code that allows anyone to serialize a malicious payload that when deserialized runs the operating system command of their choice, as the user which started the Java Virtual Machine (JVM). The vulnerabilities are not with the gadget chains themselves but with the code that deserializes them.
What is a gadget chain?
Perhaps the simplest example is a list. With some types of lists, it’s necessary to compare objects in order to determine their order in the list. For example a PriorityQueue orders objects by comparing them with each other during it’s construction. It takes a Comparator object which will call any method you choose on the objects in the list. Now if that method contains a call to
Runtime.exec(), then you can execute that code during construction of the PriorityQueue object.
There are couple of ways in which this type of attack on the JVM can be mitigated:
- not deserializing untrusted objects;
- not having the classes used in the 'gadget chain' in the classpath;
- running the JVM as a non-root operating system user, with reduced privileges;
- egress filtering not allowing any outbound traffic other than that matching a connection for which the firewall already has an existing state table entry.
The first is the best approach, as it prevents every kind of gadget chain a malicious attacker can create, even one devised from classes in the JVM itself. The second is OK, but has it's limits as there are new gadget chains made public often, and it's hard to keep up with the growing tide of them. Fortunately Enterprise Application Platform (EAP) 6 introduced module classloader that restricts which classes are available in the classpath of each module. It's much harder to find a classloader that has access to all the classes used by the gadget chain.
The 3rd and 4th option are just good general security practices. If you want to serve content on port 80 of your host, you should use a firewall, or load balancer to redirect requests from port 80 to the JVM on another port above 1024, where your unprivileged JVM process is listening. You should not run a JVM as root in order to bind to a port less than 1024, as doing so will allow a compromised JVM to run commands as root.
Egress filtering is particularly useful as a mitigation against deserialization attacks because output from the remote code execution is not returned to an attacker. The technique used by Java deserialization attacks results in the normal flow of Java execution being interrupted and an exception being thrown. So while an attacker has write and execute permissions of the user running the JVM, they don't have access to read files or shell command output, unless they can open a new connection which "phones home".
EAP 5 is still widely used, and does allow deserialization of untrusted objects via the Legacy Invoker Servlet. On top of that, its classloading structure is flat, with most libraries, including the classes from the gadget chains, available in the classpath. For anyone still running EAP 5 it is highly recommended to only bind the Legacy Invoker Servlet to a network interface card (NIC) which is not publicly accessible. This also applies to products layered on EAP 5, such as SOA-Platform (SOA-P) 5.
EAP 6 and EAP 7
While EAP 6, and EAP 7 are more robust because of the module classloader system, they can still be vulnerable. Users of these versions who are utilizing the clustering features should ensure that they are running their clustering on a dedicated Virtual Local Area Network (VLAN) and not over the Internet. That includes users of JBoss Data Grid (JDG) which uses the clustering features in the default configuration. If you don’t have a dedicated VLAN make sure you encrypt your clustering traffic. This issue is addressed in the JBoss Middleware product suite by the fix for CVE-2016-2141.
While deserialization attacks are a serious threat to JBoss Middleware, with the correct planning, and deployment configuration, the risk can be greatly reduced. Anyone running EAP 5, or layered products, should disable or restrict access to the Legacy Invoker Servlet, while anyone using the clustering feature in EAP should apply the fix for CVE-2016-2141, or make sure their clustering traffic is sent only over a dedicated VLAN.
About the author
Specializing in Kubernetes, container runtimes, and web applications, Jason Shepherd is a principal security engineer in Red Hat's Product Security team. With a passion for open source and dedication to client success, Shepherd is your go-to guy for security assessment and data for security audits.