CVE-2026-25746: 
OpenEMR vulnerability analysis and mitigation

Overview

CVE-2026-25746 is a SQL injection vulnerability in OpenEMR's prescription listing functionality, affecting all versions prior to 8.0.0. The flaw allows authenticated attackers with standard prescription (patients/rx) ACL permissions to inject arbitrary SQL commands via the sort parameter in the prescription controller. It was disclosed on February 25, 2026, with a patch released in OpenEMR version 8.0.0. The vulnerability carries a CVSS v3.1 base score of 8.8 (High) (GitHub Advisory, Feedly).

Technical details

The root cause is CWE-89 (Improper Neutralization of Special Elements used in an SQL Command). In the vulnerable code path, controller.php passes GET parameters directly to C_Prescription::list_action(), which forwards the unsanitized sort parameter to Prescription::prescriptions_factory(). That function uses add_escape_custom() — essentially a wrapper around mysqli_real_escape_string() — to sanitize the ORDER BY clause, which provides no protection against ORDER BY injection since it only escapes string delimiters. The injected value is concatenated directly into the SQL query: SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY <user_input>. The fix in version 8.0.0 replaces this with an allowlist of valid column names validated against a SORTABLE_COLUMNS constant (GitHub Advisory, Patch Commit).

Impact

Successful exploitation allows authenticated attackers to execute arbitrary SQL commands against the OpenEMR database, which stores highly sensitive protected health information (PHI). Demonstrated impacts include extraction of usernames and bcrypt password hashes from the users_secure table, unauthorized read access to patient medical records and prescriptions, potential modification or deletion of clinical data, and in some configurations, server-side code execution leading to full database compromise. Given that OpenEMR is used in healthcare settings, a breach could result in HIPAA violations and significant regulatory consequences (GitHub Advisory, PoC Repository).

Exploitability

Public proof-of-concept exploit code is available in a dedicated GitHub repository (ChrisSub08/CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4), including a Python script demonstrating boolean-based blind SQL injection to extract credentials character by character. The vulnerability requires only low-privilege authenticated access (standard patients/rx ACL), no user interaction, and is exploitable over the network. As of the time of reporting, there is no confirmed evidence of in-the-wild exploitation. The EPSS score is approximately 0.039% (low probability of near-term exploitation). The vulnerability is not listed in the CISA KEV catalog (GitHub Advisory, PoC Repository, Feedly).

Exploitation steps

  1. Obtain authenticated access: Log in to the target OpenEMR instance with any account that has the standard patients/rx ACL permission (prescription access), which is a non-elevated, commonly assigned role.
  2. Identify the vulnerable endpoint: Navigate to or craft a request targeting controller.php?prescription=&list=&id=<patient_id>&sort=<payload>, where <patient_id> is a valid patient ID (e.g., 1).
  3. Confirm injection: Send a request with a malformed sort value to trigger a SQL error and confirm the injection point:
    curl -b "OpenEMR=<session_cookie>" -k 'https://<target>/controller.php?prescription=&list=&id=1&sort="'
  4. Test time-based blind injection: Confirm blind injection using a SLEEP payload:
    curl -b "OpenEMR=<session_cookie>" -k 'https://<target>/controller.php?prescription=&list=&id=1&sort=(SELECT%20SLEEP(5))'
  5. Execute boolean-based data extraction: Use a boolean-based payload to extract data bit by bit from arbitrary tables (e.g., users_secure):
    sort=(SELECT%20((ASCII(SUBSTRING(username,1,1))%20DIV%2064)MOD%202)%20FROM%20users%20LIMIT%201)
  6. Automate extraction: Run the public Python exploit script to systematically extract all columns from target tables (e.g., usernames and bcrypt password hashes):
    python3 exploit.py <target_ip> <session_cookie> users_secure --columns username password
  7. Leverage extracted credentials: Crack extracted bcrypt hashes offline or use them for privilege escalation within OpenEMR or connected systems (GitHub Advisory, PoC Repository).

Indicators of compromise

  • Network: Unusual HTTP GET requests to /controller.php with parameters prescription=, list=, id=<integer>, and a sort= value containing SQL syntax such as parentheses, SELECT, SLEEP, ASCII, SUBSTRING, DIV, or MOD; repeated requests with incrementally varying sort payloads (indicative of boolean-based extraction).
  • Logs: Web server access logs showing requests to controller.php with URL-encoded SQL keywords in the sort parameter (e.g., %28SELECT, %20SLEEP, %20FROM%20users); PHP/application error logs containing SQL syntax error messages referencing prescriptions table and ORDER BY clause failures.
  • Database: Unusual or high-frequency queries against users_secure, users, or prescriptions tables with ORDER BY clauses containing subqueries; database slow query logs showing repeated SLEEP() calls.
  • Application: OpenEMR error output containing stack traces referencing Prescription.class.php at line 1149, C_Prescription.class.php at line 180, and Controller.class.php at line 157 (GitHub Advisory, PoC Repository).

Mitigation and workarounds

The primary remediation is to upgrade OpenEMR to version 8.0.0 or later, which replaces the ineffective add_escape_custom() sanitization with a strict allowlist of permitted column names validated in prescriptions_factory(). No official configuration-based workaround has been published; organizations unable to upgrade immediately should consider restricting access to controller.php at the web server or WAF level, and auditing accounts with patients/rx ACL permissions to minimize exposure. The patch commit is available for review at the OpenEMR GitHub repository (Patch Commit, GitHub Advisory).

Community reactions

The vulnerability was discovered by researcher Christophe SUBLET from Grenoble INP - Esisar (UGA) as part of the CyberSkills/Orion project, and was responsibly disclosed through GitHub's security advisory process. The OpenEMR maintainer bradymiller published the advisory and kojiromike contributed the remediation. Coverage appeared on The Hacker Wire and was tracked by ENISA's EUVD database (EUVD-2026-8714). Check Point also published a defense advisory (CPAI-2026-1514) referencing the vulnerability (GitHub Advisory, Check Point Advisory).

Additional resources


Source: This report was generated using AI

Related OpenEMR vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-40506HIGH7
  • OpenEMR logoOpenEMR
  • cpe:2.3:a:open-emr:openemr
NoYesAug 17, 2026
CVE-2026-76614MEDIUM5.3
  • OpenEMR logoOpenEMR
  • cpe:2.3:a:open-emr:openemr
NoYesAug 19, 2026
CVE-2026-40509MEDIUM5.3
  • OpenEMR logoOpenEMR
  • cpe:2.3:a:open-emr:openemr
NoYesAug 19, 2026
CVE-2026-40508MEDIUM5.1
  • OpenEMR logoOpenEMR
  • cpe:2.3:a:open-emr:openemr
NoYesAug 19, 2026
CVE-2026-40507MEDIUM5.1
  • OpenEMR logoOpenEMR
  • cpe:2.3:a:open-emr:openemr
NoYesAug 19, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management