Abusing Java Remote Protocols in IBM WebSphere
July 21, 2020 | Guest UserBack in April of this year, a researcher named tint0 submitted two bugs in IBM WebSphere to the ZDI program. One was an information disclosure vulnerability while the other could lead to remote code execution (RCE). This blog covers ZDI-20-689/CVE-2020-4450 and ZDI-20-690/CVE-2020-4449 – the RCE and info disclosure bugs respectively. IBM patched these bugs in June.
The Common Object Request Broker Architecture (CORBA) is a standard defined by the Object Management Group (OMG). It is a platform independent RPC framework which predates standards such as SOAP and gRPC. In a distributed setting, CORBA uses the Internet InterORB Protocol (IIOP) protocol to communicate between endpoints. In a default installation of IBM WebSphere has CORBA services running on TCP ports 2809, 9100, 9402 and 9403. Prior to invoking service methods, the call is intercepted by Interceptor classes. Of interest to us is the TxServerInterceptor
class.
receive_request()
is called when TxServerInterceptor
intercepts a call and demarshalContext()
is used to retrieve a ServiceContext
from a byte stream that can be controlled by the attacker. Arbitrary objects embedded within this byte stream are extracted by calling read_any()
which eventually results in the readObject()
method of the embedded object class being called.
The RCE Gadget (CVE-2020-4450)
Despite having the ability to deserialize any object, achieving RCE is not trivial. This is because the IBM Java SDK has implemented significant mitigations against deserialization attacks.
The mitigations relevant to this vulnerability are:
-- It has a restricted ClassLoader
to only provide necessary classes at runtime.
-- The Xalan's TemplatesImpl
TemplatesImpl class is no longer serializable. This class is often used in public gadget chains that rely on a single arbitrary method invocation.
-- The IBM SDK does not use the Oracle JDK’s implementation of the Java Naming and Directory Interface (JNDI). As a result, it is not vulnerable to remote class loading via RMI/LDAP.
In his submission, tint0 provided a gadget that bypasses these mitigations. This gadget uses the WSIFPort_EJB
class as an entry point.
This class does a few interesting things inside the getEJBObject()
method. Let us start by looking at the JNDI lookup call.
As shown, getObjectInstanceViaContextDotObjectFactories()
can result in the invocation of getObjectInstance
of any ObjectFactory
class. One such class which is relevant to this gadget is WSIFServiceObjectFactory
:
The getObjectInstance()
call will initialize a Web Services Invocation Framework (WSIF) service from a URL pointing to a remote XML definition that can be controlled by the attacker. In this specific scenario, the service’s className
is set to javax.el.ELProcessor
, and a java:operation
element is defined that maps findByPrimaryKey()
to the eval()
Java method. For further details on WSIF services, please refer to this website.
The getObjectInstance()
call returns a WSIFClientProxy
Java proxy object. This proxy object will invoke eval() on an instance of ELProcessor
when findByPrimaryKey()
is called. Recall that we already control the argument this.key
via deserialization. This results in RCE via Expression Language injection. The following video demonstrates this PoC in action.
The Information Disclosure Gadget (CVE-2020-4449)
This gadget is due to an XXE when parsing the WSIF service definition XML described above. The vulnerable code is shown below:
This gadget also demonstrates bypassing mitigations in modern JREs. Specifically, out-of-band extraction (eg: via FTP) is prevented in modern JREs. In this particular case, the data is extracted via error messages, so it is critical that the parsing of the XML document is not wrapped in a try/catch statement. The following video shows this gadget in action:
The Patch
To address these vulnerabilities, IBM took steps to ensure the TxServerInterceptor
class no longer deserializes arbitrary objects. Instead, the specific properties are extracted from the input steam via the use of helper classes.
Conclusion
In recent times, Java deserialization vulnerabilities have proven to be dangerous and often result in reliable remote code execution. Despite the mitigations in modern Java SDKs, tint0 showed how reliable exploitation of this bug class is still possible. For further reading, we recommend tint0’s talk titled “Far Sides of Java Remote Protocols” [PDF] from Black Hat EU 2019. We look forward to receiving more high-quality web application vulnerabilities like this in the future.
You can find me on Twitter at @zebasquared, and follow the team for the latest in exploit techniques and security patches.