This is a bad lock on a storage closet, not an open vault on the sidewalk
CVE-2025-0230 is a SQL injection flaw in code-projects Responsive Hotel Site affecting version 1.0, specifically the /admin/print.php path where the pid parameter is not safely handled. Public PoC material says an attacker can manipulate pid to alter backend SQL queries, which means data readout, tampering, or destructive queries against the app database are plausible if the page is reachable.
The vendor/CNA MEDIUM score is still a bit generous for enterprise prioritization. The decisive friction is that the vulnerable endpoint lives under /admin/ and the CNA vector says PR:L, so this is not a clean internet-scale pre-auth exploit; it is a post-auth app-layer bug in a lightly maintained sample PHP project that the vendor itself documents for localhost XAMPP/WAMP-style deployment.
4 steps from start to impact.
Get to the admin surface
/admin/print.php. In practice this usually means the app is externally exposed or the attacker already has internal access to a dev/test segment. Tooling is trivial here: a browser, curl, Burp Suite, or ffuf is enough to verify the path exists.- Responsive Hotel Site
1.0is deployed at all - The web server exposes the
/admin/area to the attacker's network position - The attacker can reach the PHP app over HTTP/S
- The product page explicitly describes
localhostXAMPP/WAMP deployment, which strongly suggests many installs are lab, student, or dev-only - There is no strong product fingerprint or reliable internet exposure dataset for this sample app
- Many enterprises will not knowingly run this project in production
/admin/.Satisfy the privilege requirement
PR:L, so exploitation assumes at least low privileges rather than anonymous internet access. That means the attacker needs valid app credentials, a hijacked session, or some other foothold that gets them past the app's access controls. Common offensive tooling here is Burp Suite session replay or credential stuffing against weak demo credentials if admins left them unchanged.- Valid low-privileged or admin-capable application session
- Authentication is enforced the way the CNA score implies
- This prerequisite already assumes a prior compromise stage or exposed weak credentials
- MFA, SSO front-ends, VPN gating, or simple IP restrictions can kill the path before the SQLi matters
- If the admin area is broken or disabled, the vulnerable path may be unreachable in practice
Inject through pid
/admin/print.php?pid=... and test for injection using sqlmap, manual UNION SELECT probes, or boolean/time-based payloads. The public PoC explicitly points to pid and describes UNION-style extraction. If the backend query is reachable as described, database contents tied to reservations, bookings, or admin data can likely be enumerated.- The vulnerable
admin/print.phpfile is present pidflows into a SQL statement without proper parameterization- Database errors or response differences are observable enough to exploit
- Custom error handling, generic responses, or WAF rules can slow exploitation
- Some installs may have code drift or local edits that break the PoC
- Least-privileged DB accounts can limit what the injection can actually do
UNION, comment, and timing payloads; SAST/grep-based code review can also spot raw pid use in print.php.Turn app DB access into actual impact
- Successful SQL injection
- Useful data or dangerous DB permissions behind the vulnerable query
- Blast radius is usually confined to one app and its database
- No evidence here of direct OS-level RCE or cross-tenant spread
- Modern monitoring may flag anomalous SQL volume or destructive queries
The supporting signals.
| In-the-wild status | No authoritative evidence of active exploitation found. CISA KEV: not listed; OpenCVE also shows KEV no. |
|---|---|
| Public PoC | Yes. Public PoC/notes exist in GitHub by Huandtx, naming /admin/print.php and the pid parameter, with UNION-style SQLi discussed. |
| EPSS | 0.00097 from the prompt intel, which is extremely low predicted exploitation probability. Third-party trackers around this CVE also show EPSS in the ~0.001 range. |
| KEV status and dates | Not present in the CISA Known Exploited Vulnerabilities Catalog as checked for this assessment. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L matters because PR:L means authenticated/post-auth, not anonymous pre-auth internet exploitation. |
| Affected versions | Authoritative records consistently name Responsive Hotel Site 1.0 as affected. I found no broader maintained version range. |
| Fixed version | No official vendor fix or maintained patched version was identified. Treat this as unpatched abandonware/demo code unless your team has locally corrected print.php. |
| Exposure and scanning | Shodan's CVEDB tracks the product and multiple related CVEs, but I found no trustworthy host-count or fingerprint-based internet exposure metric. Inference: real-world exposed population is probably small and hard to measure because this is a sample PHP project, not a mainstream enterprise platform. |
| Disclosure and provenance | Published 2025-01-05 via VulDB/CVE feeds. NVD later added a divergent 9.8 enrichment even though the CNA data and the /admin/ path support a more constrained interpretation. |
noisgate verdict.
The single biggest driver downward is the PR:L authenticated requirement on an /admin/ endpoint, which makes this a post-auth application bug rather than a broad unauthenticated edge compromise. The other major suppressor is population: this is a niche sample PHP project documented for localhost deployment, so the exposed enterprise install base is likely tiny compared with products that deserve emergency patch motion.
Why this verdict
- Post-auth, not pre-auth: the CNA vector is
PR:L, so the exploit chain starts after the attacker already has credentials or a session. - Reachability is narrow: the vulnerable code is under
/admin/print.php, which removes a lot of opportunistic anonymous scanning value. - Tiny real deployment population: the vendor page describes
localhostXAMPP/WAMP use for a free sample project, not a broadly deployed enterprise product. - Threat telemetry is cold: no KEV listing, no active exploitation evidence found, and EPSS is near zero.
- Blast radius is usually app-local: compromise is meaningful for this app and DB, but there is no evidence here of direct OS-level code execution.
Why not higher?
If this were unauthenticated on a mainstream internet-facing product, the score would climb fast. But every real-world friction point pushes the other way: niche software, likely dev/lab installs, admin-path reachability, and a PR:L requirement. NVD's 9.8 enrichment looks like a vacuum-score mistake for operational prioritization.
Why not lower?
It is still bona fide SQL injection with public exploit guidance, not a theoretical bug. If you do run this app and the admin area is reachable to untrusted users or weak credentials exist, an attacker can likely read or alter the app database, so IGNORE would be too dismissive.
What to do — in priority order.
- Pull the admin path behind identity controls — Require VPN, reverse-proxy auth, IP allowlisting, or equivalent in front of
/admin/. For aLOWnoisgate verdict there is no SLA; treat this as backlog hygiene, but do it whenever the app is still exposed to anything broader than trusted admins. - Block obvious SQLi patterns at the edge — Add WAF rules for
UNION, comment markers, stacked queries, and time-based payloads onpidrequests toprint.php. This is a containment move when no official patch is available; forLOW, there is no deadline pressure, but it is worth doing if you cannot retire the app. - Constrain the database account — Ensure the PHP app uses a DB account without schema-altering or file-write privileges. That reduces SQLi impact from 'full DB abuse' to 'nuisance/local data tampering' and is appropriate backlog work for a low-priority demo app.
- Decommission or replace the sample app — The stronger long-term control is to remove tutorial/demo code from any environment that matters. No official fixed release was identified, so replacement or retirement is often cleaner than trying to maintain a fork.
- Add authenticated DAST coverage — If this app must stay, scan it with credentials so
/admin/endpoints are actually tested. This is the right verification loop for low-priority but real app-layer bugs that unauthenticated scanners routinely miss.
- Blindly prioritizing the NVD
9.8score doesn't help; it overstates the real attack path because it ignores the CNA'sPR:Lconstraint. - Network IDS signatures alone are weak here; simple parameter changes or HTTPS termination gaps will miss app-layer SQLi without context.
- Patching the OS or PHP runtime does not fix this bug; the flaw is in the application's request handling and SQL construction.
Crowdsourced verification payload.
Run this on the target web server or on a mounted copy of the application source tree. Invoke it as python3 verify_cve_2025_0230.py /var/www/html/responsive-hotel-site on Linux/macOS or py verify_cve_2025_0230.py C:\xampp\htdocs\responsive-hotel-site on Windows; it only needs read access to the app files.
#!/usr/bin/env python3
# verify_cve_2025_0230.py
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN / usage / unreadable
import os
import re
import sys
TARGET = os.path.join('admin', 'print.php')
PATTERNS = [
re.compile(r"\$_(GET|REQUEST|POST)\s*\[\s*['\"]pid['\"]\s*\]", re.I),
re.compile(r"pid\s*=\s*\$_(GET|REQUEST|POST)", re.I),
re.compile(r"select\s+.*\$[A-Za-z_][A-Za-z0-9_]*", re.I | re.S),
re.compile(r"mysql_query\s*\(", re.I),
re.compile(r"mysqli_query\s*\(", re.I),
]
SAFE_HINTS = [
re.compile(r"prepare\s*\(", re.I),
re.compile(r"bind_param\s*\(", re.I),
re.compile(r"execute\s*\(", re.I),
re.compile(r"intval\s*\(\s*\$_(GET|REQUEST|POST)\s*\[\s*['\"]pid['\"]\s*\]\s*\)", re.I),
re.compile(r"filter_input\s*\(", re.I),
]
def find_target(root):
direct = os.path.join(root, TARGET)
if os.path.isfile(direct):
return direct
matches = []
for base, _, files in os.walk(root):
if 'print.php' in files and os.path.basename(base).lower() == 'admin':
matches.append(os.path.join(base, 'print.php'))
return matches[0] if matches else None
def main():
if len(sys.argv) != 2:
print('UNKNOWN - usage: verify_cve_2025_0230.py <app_root>')
sys.exit(2)
root = sys.argv[1]
if not os.path.isdir(root):
print('UNKNOWN - supplied path is not a directory')
sys.exit(2)
target = find_target(root)
if not target:
print('PATCHED - admin/print.php not found under supplied path')
sys.exit(0)
try:
with open(target, 'r', encoding='utf-8', errors='ignore') as f:
data = f.read()
except Exception as e:
print(f'UNKNOWN - cannot read {target}: {e}')
sys.exit(2)
has_pid = any(p.search(data) for p in PATTERNS[:2])
has_sql = any(p.search(data) for p in PATTERNS[2:])
has_safe = any(p.search(data) for p in SAFE_HINTS)
if has_pid and has_sql and not has_safe:
print(f'VULNERABLE - {target} references pid and appears to build/issue SQL without obvious parameterization')
sys.exit(1)
if has_pid and has_safe:
print(f'PATCHED - {target} references pid but shows signs of input handling or prepared statements')
sys.exit(0)
if has_pid and not has_sql:
print(f'UNKNOWN - {target} references pid, but the script could not confirm SQL usage')
sys.exit(2)
print(f'UNKNOWN - {target} did not match the expected vulnerable pattern')
sys.exit(2)
if __name__ == '__main__':
main()
If you remember one thing.
/admin/ behind trusted access and add a simple WAF rule during normal backlog cleanup. For a LOW verdict there is no noisgate mitigation SLA and no noisgate remediation SLA; treat it as backlog hygiene, document any exposed instances, and either retire the app or locally fix the vulnerable print.php path rather than burning emergency patch capacity on it.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.