Oracle Access Manager Pre-Auth RCE (CVE-2021–35587 Analysis)
As you may know, Oracle Access Manager (OAM) is a popular SSO product used by many big corp such as Oracle, VMware, Huawei, Qualcomm, …
This vulnerability was discovered by accident by me and Peterjson while we were analyzing and building PoC for another mega-0day (which is still not fixed by now ;) ).
It’s quiet easy to access the entrypoint and exploit the vulnerability, so it’s recommend to apply the patch now! It may give the attacker access to OAM server, to create any user with any privileges, or just get code execution in the victim’s server.
We used these guides to setup the lab:
The setup part is pain in the ass, it took us a month to setup a fully functional lab (╯‵□′)╯︵┻━┻. We almost gave up after two week of trying!
Till now, we’ve completely forgotten everything about that, so we can not help if you get any setup trouble ¯\_(ツ)_/¯.
In this post, i will provide details about the vulnerability in the OAM 12c version. With OAM 11g version, it will need more complicated “thing” to get RCE. (Fact: most public targets are still using OAM 11g instead of 12c ;) ).
Let’s start by taking a look at URL endpoint “/oam/server/opensso/sessionservice” which is being handled by the class “oracle.security.am.pbl.transport.http.AMServlet”:
The “AMServlet.doPost()” didn’t do much job, it just call handleRequest() then PBLFlowManager.processRequest() to process incoming request:
In PBLFlowManager.processRequest(), our incoming URI “/oam/server/opensso/sessionservice” is mapped to an event Name called “OPENSSO_CHECK_VALID_SESSION”:
Next, an EventHint is created from given eventName, then the requestHandler is get from a map using that eventHint:
In this case, the requestHandler is an instance of AgentRequestHandler, there is also a bigger list of these handler endpoint mapping, but I don’t remember where it is yet 🤷:
From PBLFlowManager.handleBaseEvent(), the request flow is divined in two parts:
- First part: call the requestHandler.process() to parse, validate incoming XML data
- Second part: call the PBLFlowManager.delegateToMasterController() to handle the logic feature of current request
In the first part, AgentRequestHandler.process() will call handleXMLRequest() to parse the incoming data as XML data:
After having successful parsed the data as a XML request, this method continue to jump into AgentRequestHandler.handleRequest()
To get pass the isValid() method, the incoming request must follow this form:
<?xml version=”1.0" encoding=”UTF-8" standalone=”yes”?><RequestSet vers=”vers123" svcid=”session” reqid=”req_1”><Request dtdid=”dtd1" sid=”sid1">Data</Request></RequestSet>
Then, it will call getServiceHandler() with parameter “serviceId” (which can be fully manipulated):
There’re 4 types of serviceHandler based on 4 svcid:
- NamingService with svcid: com.iplanet.am.naming
- AuthXMLHandler with svcid: auth
- SessionRequestHandler with svcid: session
- PolicyXMLHandler with svcid: policy
In this case, we’re focusing on the SessionRequestHandler:
After successful determined the sessionHandler, AgentRequestHandler.handleRequest() will continue to call our given sessionHandler.process(), now is SessionRequestHandler.process().
In SessionRequestHandler.process(), it will get the data from the xml tag named “Request” and parse this data again as XML data:
Just take the attention at SessionRequestParser.parseXML(), if the incoming xml request contains an attribute named “requester”, then its’ data will be base64 decoded and set as an property named “Requester”:
At this, our request data looks like this:
It sounds straight when reading this document, but you should try it yourselves, it’s not easy to complete this data!
After having successful parsed the incoming XML data, we continue with the second part, PBLFlowManager.handleBaseEvent() will continue to call delegateToMasterController() -> MasterController.process() -> MasterController.processRequest() -> OpenssoEngineController.processEvent(), here is the call frame:
*The OpenssoEngineController is determined by the given EventHint mentioned above.
In the OpenssoEngineController.processEvent(), there’s a switch case statement to handle each event type, in our case, it’s the OPENSSO_CHECK_VALID_SESSION:
Follow this branch, we will see a call to the OpenssoEngineController.unmarshal() method with given “requester” attribute:
And this is the content of unmarshal() method:
We can quickly see that, if the “requester” attribute has the form of “object:<base64 data>”, then this data will be directly deserialize without any filtering.
And that’s the sink of this vulnerability, long speaking, here is how the request looks like:
Lucky for us, OAM is built on top of weblogic, and the OAM’s classloader also contains weblogic’s libraries. So yeah, we can use some weblogic gadgetchain to get RCE.
After having tried many old gadgetchain, we found that the CVE-2020–14644 gadgetchain is still not blocked by the global serialization filter yet. And our final PoC also used this gadgetchain to get RCE!
After successfully demonstrate the PoC on OAM 12c, we’ve tried to apply the latest patch for this OAM instance and guess what, our PoC is not exploitable anymore (╯°□°）╯︵ ┻━┻.
At first, we thought that Oracle has already known about this vulnerablity and managed to patch it. After reviewing the patch and checking the older version, we know that they didn’t.
The reason is: In the recent patch of OAM 12c, they dropped support for OpenSSO, so the entrypoint “/oam/server/opensso/sessionservice” is also removed by accident. But not for the OAM 11g ;), we found out that the vulnerable entrypoint still existed in a fully updated OAM 11g.
In OAM 11g, the gadgetchain of CVE-2020–14644 doesn’t exist, so it required more work to build a working gadgetchain. The journey to get RCE on OAM 11g is another interesting story, so we decided to talk about it later!
Wanna here another fact?
Weblogic 10.3.6 and OAM 11g have already been End-Of-Life, there is no patch for them after Jan 1st/2022.
Which mean: there is no patch for this Pre-Auth RCE ¯\_(ツ)_/¯
Thank you for reading!
And have fun with this 0.5day!
By Jang & Peterjson