Posted by David Bohannon on Tuesday, June 14th, 2016
Multiple versions of JBoss contain a vulnerability that can allow remote users to execute arbitrary code on the server running JBoss; mitigating this issue is not always as simple as upgrading JBoss to the latest version. The Java deserialization vulnerability (CVE 2015-7501 and CWE-502, disclosed in January 2015) affects specific classes within the Apache Commons-Collections library prior to versions 3.2.2 and 4.1; this vulnerability allows remote code execution by an unauthenticated attacker. The Apache Commons-Collections library is included in multiple middleware technologies, including JBoss application servers. JBoss is of particular interest because the invoker servlets which pass serialized objects to the vulnerable Commons-Collections classes are made available over the HTTP web listener (i.e., port 80, 8080, etc.), increasing the likelihood that they are externally accessible beyond corporate firewalls and available to an attacker. Default configurations of JBoss versions 4.3.x, 5.x, and 6.x contain the vulnerable Commons-Collections library and have the invoker servlets enabled; however, the invoker servlets are not enabled by default in JBoss version 7.x.
The affected classes within the Apache commons-collections library are CloneTransformer, ForClosure, InstantiateFactory, InstantiateTransformer, InvokerTransformer, PrototypeCloneFactory, PrototypeSerializationFactory, and WhileClosure. These classes, which are often used for creating or cloning objects, automatically execute commands provided in serialized input. While some applications may directly leverage the vulnerable Commons-Collections classes mentioned above, the application does not need to call these classes to be vulnerable since the JBoss application server already provides an attack vector via the invoker servlets as we will see below.
The Java deserialization vulnerability is exploitable in several invoker servlets in JBoss application servers where untrusted serialized Java objects received over HTTP(S) are passed to the vulnerable Commons-Collections classes. A remote attacker can supply a command of his or her choosing to one of the invoker servlets, and the vulnerable class will execute it. Because the JBoss invoker servlets pass untrusted serialized Java objects to the vulnerable classes prior to authentication, an unauthenticated attacker can exploit this.
In order to determine if an instance of JBoss is vulnerable, we need to determine whether it contains the vulnerable Commons-Collections library and whether we can pass a serialized payload to one of the vulnerable classes mentioned above.
To determine if the JBoss instance contains the vulnerable library, simply grep for one of the vulnerable classes in your JBoss installation directory. In the screenshot below, we see that our instance of JBoss 6.1.0 contains several instances of the vulnerable “commons-collections-3.2.jar” that may be exploited.
To determine whether we can access the vulnerable classes, we will attempt to communicate with one of the following servlets by sending a request to it from a browser:
As shown below, we see the invoker servlets return a serialized Java object if they are listening and accessible.
Our JBoss instance contains the vulnerable library and has a viable attack vector via the JMXInvokerServlet. We can now conduct a proof-of-concept exploitation to validate the vulnerability.
To generate our payload, we use the “ysoserial” payload generator available on GitHub. Using the following command, we create a payload that will ping our system from the vulnerable server:
java -jar ysoserial-0.0.4-all.jar CommonsCollections1 'cmd /c ping 10.0.2.6' > /home/db/Desktop/ping
If we inspect our payload with the “xxd” hexdump utility, we see it contains a serialized Java object containing our ping command.
Using Burp Suite, we intercept a request from our browser to the JMXInvokerServlet and inject our payload into the request body using the “paste from file” feature. As shown in the request below, our serialized payload containing our ping command has been inserted into the request body. We now submit our modified request and payload to the vulnerable JBoss server.
Using Wireshark on our testing system, we can see the ping emanating from our vulnerable JBoss server at 10.0.2.15, verifying that our remote code execution was successful.
The benefit of using the ping command for testing is that we are not modifying the victim system, and we do not need access to the victim system via SSH, local accounts, etc. to verify whether the payload executed successfully.
The two most viable remediation options for the Java deserialization vulnerability in JBoss application servers are: upgrade the Apache Commons-Collections library, or disable or restrict the known attack surface. Apache has released two patched versions of the Commons-Collections library, versions 3.2.2 and 4.1, which disable deserialization in the known vulnerable classes listed above. Red Hat has also released updates which will upgrade the JBoss Commons-Collections library to a safe version. However, if an application relies on the deserialization functionality in the vulnerable classes, then upgrading to the patched version may break the application, so extensive regression testing should be conducted. Because of this, the preferred method of remediation is often to disable or restrict access to the attack surface that passes untrusted serialized Java objects to the vulnerable classes. Within JBoss, the known attack surface consists of the invoker servlets, specifically the JMXInvokerServlet, EJBInvokerServlet, EJBInvokerHAServlet, and JMXInvokerHAServlet. Other JBoss listeners that accept serialized Java objects are the JNDIFactory, AJPConnector, JMXMbeanServer, JNDIService, RMIServerSocket, and JbossRemotingConnector listeners; however, we have not successfully conducted or found any proof-of-concept exploitation of these listeners.
Disabling the vulnerable listeners within the JBoss configuration files is the most secure method of mitigating the vulnerability. An alternative is to simply restrict access to these listeners. The four invoker servlets listen on the HTTP web interface, so we cannot use firewall rules to drop traffic to the servlets. Instead, a reverse proxy can be configured to only allow traffic destined for specific application routes and drop traffic destined for the vulnerable invoker servlets. The other listeners mentioned above run on separate ports, and access to them can be restricted with firewall rules.
It is also worth noting that web application firewalls (WAFs) are not always effective at mitigating this issue. The WAF must be configured to decode base64 encoded transmissions and drop requests containing malicious keywords. However, blacklisting malicious input is generally considered a weak practice as malicious payloads can often be manipulated to bypass WAF filters.
Get the latest AppSec news and trends sent directly to you.