A learn-to-code hospital app with a SQL injection bug that exists in fifty other places in the same codebase
CVE-2026-13548 is an authenticated SQL injection in /doctortimings.php via the editid parameter of itsourcecode's *Hospital Management System v1.0* — a free PHP/MySQL demo project distributed via itsourcecode.com as student/portfolio material. An attacker who already holds a valid login can inject arbitrary SQL via editid, reading, modifying, or destroying database contents. The codebase has *no version branching* — there is one v1.0 and dozens of sibling CVEs (13520, 13530, 13531, etc.) reporting the same mysqli_query($_GET[...]) antipattern in adjacent files.
The vendor MEDIUM/6.3 rating is technically defensible under CVSS math (network vector, low complexity, low privs, low CIA) but operationally inflated. This is not enterprise software. It has no support contract, no patch pipeline, and almost no real-world deployments outside coursework, portfolios, and the occasional under-resourced clinic running a copy-pasted intern project. For a defender managing 10,000 hosts: if you find this in production, the SQLi is the least of your problems.
4 steps from start to impact.
Obtain valid credentials
PR:L — the attacker must authenticate first. In a stock install that means any staff/doctor/receptionist account. Common acquisition: default creds shipped with the demo (admin/admin), credential stuffing against the public login form, or self-registration if enabled.- App reachable on the network
- Working credential set or self-registration
- Most deployments are internal-only LAN
- Demo apps often killed before production
Reach /doctortimings.php?editid=…
GET to /doctortimings.php with the editid parameter. The parameter is concatenated directly into a mysqli_query() UPDATE/SELECT call with no prepared statements or input filtering.- Active PHP session cookie
- Network reachability to the web tier
- App typically behind clinic LAN, no WAN exposure
- Shodan/Censys footprint is negligible
Inject via sqlmap
sqlmap -u 'http://target/doctortimings.php?editid=1' --cookie='PHPSESSID=…' --dbs --batch. The PHP/MySQL stack and lack of stacked-query protection make union- and error-based extraction trivial.- sqlmap or equivalent injection tool
- None — once you have the cookie this is a 30-second job
Database read/modify/destroy
C:L/I:L/A:L — partial impact on each axis because the MySQL user is application-scoped and cannot necessarily read every schema or drop the instance. Patient PII, appointment records, and billing tables are reachable. RCE is not in scope; INTO OUTFILE requires FILE privilege which the bundled DB user lacks by default.- Bug is exploitable end-to-end
- Stock MySQL user privileges restrict file write / OS pivot
- PHI leak triggers HIPAA/GDPR but not lateral movement
The supporting signals.
| In-the-wild exploitation | None observed. No campaign attribution, no honeypot hits tied to this specific endpoint. |
|---|---|
| Proof-of-concept | Public PoC referenced on GitHub via GHSA-pqf9-gv8x-vr6w; trivially reproducible with sqlmap — no custom tooling needed. |
| EPSS | Expected <0.5% (typical for itsourcecode CVE class — siblings 13520/13530/13531 all sit <0.001 percentile). |
| KEV status | Not listed. No itsourcecode product has ever been added to CISA KEV. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L → 6.3 MEDIUM. The PR:L is the load-bearing element holding this above LOW. |
| Affected versions | itsourcecode Hospital Management System v1.0 — the only version that exists. No upstream successor. |
| Fixed version | None. Vendor does not maintain a patch pipeline; no commit, no advisory, no fix. |
| Internet exposure | Shodan/Censys footprint for this app is negligible — under a few hundred hosts globally; most behind NAT/clinic LANs. |
| Disclosure | 2026-06-29, reported by *Vivian* via VulDB community submission. |
| Sibling CVEs | CVE-2026-13520, 13530, 13531, 13548 — same codebase, same mysqli_query($_GET[...]) antipattern, different files. Patching one without auditing all is theater. |
noisgate verdict.
Downgraded to LOW because the single most decisive factor is *installed base*: itsourcecode Hospital Management System is a free demo/portfolio PHP project with effectively zero enterprise footprint, no patch pipeline, and authenticated-only exploitation. Even successful exploitation yields partial CIA against a sandboxed app DB — not domain, identity, hypervisor, or supply-chain compromise.
Why this verdict
- Authentication required (PR:L): the attacker must already hold valid app credentials — this is post-access SQLi, not unauthenticated RCE.
- Installed base is effectively zero in the enterprise: itsourcecode is a free PHP teaching codebase; no Fortune-2000 procurement, no HIPAA-audited deployment, no support contract.
- Role multiplier — low-value role: the affected component is a standalone PHP/MySQL line-of-business app. It is not an IdP, hypervisor, CA, PAM, backup server, EDR, or network edge appliance. Worst-case blast radius is one application database with partial CIA impact.
- Role multiplier — typical role: small clinic intranet server. Compromise = PHI exposure in that one tenant; no lateral pivot path inherent to the bug.
- Role multiplier — high-value role: does not exist. This software is never canonically deployed as identity, trust, or orchestration infrastructure. Floor logic does not apply.
- No KEV, no campaigns, no EPSS heat. Sibling CVEs in the same product family carry sub-1st-percentile EPSS scores and zero observed exploitation.
- No patch exists and likely never will — but a missing patch on abandoned demo software is a *procurement* failure, not a severity multiplier.
Why not higher?
MEDIUM would require either a credible enterprise installed base, unauthenticated exploitation, or a high-value-role deployment pattern. None apply: PR:L gates the attack, installed base is academic, and the impact ceiling is one app schema with partial CIA.
Why not lower?
IGNORE is wrong because the bug is real, the PoC works, and clinics *do* sometimes deploy this. If you have it in your fleet, you need to know — and you need to replace it, not patch it. LOW captures backlog-hygiene urgency without misallocating SOC attention.
What to do — in priority order.
- Inventory first — confirm whether you actually run itsourcecode HMS — Run an authenticated scan or grep your CMDB for
itsourcecode,hospital management,doctortimings.php. If nothing matches, close the ticket. No mitigation SLA applies at LOW; this is pure asset discovery hygiene. - If found, take the app offline or wall it behind VPN+MFA — There is no vendor patch. The only sustainable control is to remove WAN exposure entirely and gate it behind authenticated VPN with MFA. Schedule a replacement project (commercial EMR or maintained open-source like OpenEMR) — treat as backlog hygiene under the 365-day remediation window since no mitigation SLA applies at LOW.
- Force a credential reset and disable self-registration — Because the bug requires PR:L, the entire attack surface is gated by who holds an account. Rotate all app credentials, kill default
admin/admin, and turn off self-signup if present. - Drop a WAF rule on
editidand sibling parameters — ModSecurity CRS rules 942100–942470 already cover this. Verify they are in blocking mode on this vhost. Also instrument the *other* itsourcecode CVEs — siblings 13520, 13530, 13531 hit different files with identical patterns. - Tighten the MySQL service account — Strip
FILE,PROCESS, and any DDL privileges beyond what the app strictly needs. This is what keeps aC:L/I:L/A:Loutcome from being upgraded by an attacker pivoting to OS-level viaINTO OUTFILE.
- EDR on the web server — SQLi happens at the database query layer; the PHP process behaves normally from a host-IOC perspective.
- Network segmentation alone — authenticated insiders or any compromised low-priv account can still hit the endpoint.
- Waiting for a vendor patch — itsourcecode does not ship security updates. You will wait forever.
Crowdsourced verification payload.
Run on your auditor workstation or any host that can reach the target app. Provide the target base URL and a valid authenticated session cookie. No root required. Example: ./check_cve_2026_13548.sh https://hms.internal.example.com 'PHPSESSID=abcdef123456'.
#!/usr/bin/env bash
# noisgate verification — CVE-2026-13548
# itsourcecode Hospital Management System 1.0 — SQLi in /doctortimings.php (editid)
# Usage: ./check_cve_2026_13548.sh <base_url> <session_cookie>
set -u
BASE="${1:-}"
COOKIE="${2:-}"
if [[ -z "$BASE" || -z "$COOKIE" ]]; then
echo "Usage: $0 <base_url> <session_cookie>" >&2
exit 2
fi
TARGET="${BASE%/}/doctortimings.php"
# 1) Confirm the endpoint exists at all
CODE=$(curl -s -o /dev/null -w '%{http_code}' -b "$COOKIE" "$TARGET?editid=1")
if [[ "$CODE" == "404" ]]; then
echo "PATCHED (endpoint not present — likely not itsourcecode HMS)"
exit 0
fi
# 2) Time-based blind SQLi probe — 5s SLEEP
START=$(date +%s)
curl -s -o /dev/null -b "$COOKIE" --max-time 15 \
"$TARGET?editid=1%20AND%20SLEEP(5)--%20-"
END=$(date +%s)
DELTA=$((END-START))
if (( DELTA >= 5 )); then
echo "VULNERABLE (time-based SQLi confirmed on editid, delay=${DELTA}s)"
exit 1
fi
# 3) Error-based probe — broken quote
RESP=$(curl -s -b "$COOKIE" --max-time 10 "$TARGET?editid=1'")
if echo "$RESP" | grep -Eqi 'sql syntax|mysqli?_|mysql_fetch|you have an error in your sql'; then
echo "VULNERABLE (error-based SQLi confirmed — DB error string leaked)"
exit 1
fi
echo "UNKNOWN (endpoint reachable but no injection signal — verify cookie validity)"
exit 3
If you remember one thing.
Sources
- Vulnerability-Lookup — CVE-2026-13548
- GitHub Security Advisory GHSA-pqf9-gv8x-vr6w
- VulDB CVE index
- OffSeq Threat Radar — sibling CVE-2026-13520 (same codebase)
- OffSeq Threat Radar — sibling CVE-2026-13530
- OffSeq Threat Radar — sibling CVE-2026-13531
- CWE-74 — Injection
- OWASP SQL Injection Prevention Cheat Sheet
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.