This is a sharp knife left in a toy kitchen, dangerous if you actually put it on the counter
CVE-2025-0204 is a SQL injection flaw in code-projects Online Shoe Store 1.0, specifically in /details.php via the id parameter. The published proof of concept shows the app reading $_GET['id'] directly into SELECT * FROM product WHERE product_id = '$id', which makes database extraction straightforward if this sample PHP app is deployed and reachable.
The vendor's MEDIUM 6.3 baseline is technically plausible for a single exposed app, but it overstates fleet-level urgency for most enterprises. The big reality check is *reach*: this is a low-prevalence code-projects sample app, not Exchange, Ivanti, or a common edge platform; there is no KEV listing, no observed mass exploitation signal in the sources reviewed, and the scary sqlmap-to-shell outcome depends on extra database and filesystem privileges that many real deployments will not grant.
4 steps from start to impact.
Find a live instance
- The organization is actually running
code-projects Online Shoe Store 1.0 - The app is reachable over HTTP/HTTPS from the attacker position
- This product has very low enterprise prevalence
- There is no strong internet-wide fingerprint in the reviewed sources, so finding targets at scale is noisy
- Many enterprises will not run code-projects sample apps in production at all
/details.php?id=; scanner coverage is mostly custom rather than turnkey.Exploit details.php?id= with sqlmap
th4s1s shows sqlmap-style exploitation against /details.php by manipulating the id parameter. The CVE record says PR:L, but the code path and product behavior strongly suggest this page is part of normal product browsing and likely reachable without authentication.- The vulnerable
details.phpcode is present - The page accepts attacker-controlled
idinput - The database query is not parameterized
- If the site is tucked behind VPN, IP allowlists, or private ingress, the bug becomes post-initial-access
- A WAF with competent SQLi signatures may block commodity payloads
- Some deployments may have modified the sample code
/details.php?id=1' are effective. Generic SAST/secret scanning will not help unless you scan the PHP source.Read or modify the app database
- The DB account used by the app has useful read/write access
- The underlying DB error handling does not fully suppress exploitation
- Least-privilege DB users can sharply limit impact
- Data value may be low if the app is only a demo or coursework deployment
- If the database is separate and tightly permissioned, blast radius stays local to this app
sqlmap-style request bursts only indirectly through web logs.Attempt OS-level pivot
sqlmap file-write or command-execution features. That is *not* the default outcome of SQLi; it usually requires database features like FILE, stacked queries, writable web roots, or risky DB-to-OS integrations.- Database user has elevated privileges beyond normal app reads/writes
- The DBMS and web stack allow file write or command execution paths
- The attacker can place or execute a web shell or equivalent payload
- Many real deployments will not grant DB
FILEprivilege or equivalent - Separate DB hosts and non-writable web roots break the easy
sqlmap --os-shellstory - Modern EDR or file integrity monitoring can catch shell drops
The supporting signals.
| In-the-wild status | No authoritative in-the-wild exploitation evidence found in the reviewed sources. CISA KEV: not listed as of the latest catalog page reviewed (KEV catalog). |
|---|---|
| Public PoC availability | Yes. A public gist by th4s1s shows the vulnerable code path and sqlmap exploitation workflow (gist). |
| EPSS | User-supplied EPSS is 0.00056 (~0.056%), which is very low and consistent with a niche target population. FIRST documents EPSS as a daily probability model via its public API (FIRST EPSS, API). |
| KEV / CISA status | The CVE is present in CISA's weekly vulnerability bulletin for the week of December 30, 2024, but not in the Known Exploited Vulnerabilities catalog (weekly bulletin, KEV catalog). |
| CVSS vector reality check | Published vector is 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 field looks questionable because the vulnerable path is /details.php?id= and the PoC targets normal product-detail browsing rather than an admin-only function (CVE JSON, PoC gist). |
| Affected versions | Officially affected version range is just Online Shoe Store 1.0 in the CVE record (CVE JSON, NVD). |
| Fixed version | No vendor-fixed version is identified in the CVE record or product page review. Treat this as no official patch published from the sources reviewed (OpenCVE, product page). |
| Scanning / exposure data | No trustworthy internet-scale exposure count was found during review. Analyst assessment: this is likely a small, long-tail exposure set made up of demo, lab, or neglected PHP sites rather than widely managed enterprise fleet software. |
| Disclosure and reporter | Published on 2025-01-04; timeline notes advisory disclosure on 2025-01-03. Reporter credit in the CVE JSON is lio346 (VulDB User) (CVE JSON). |
| Research context | The same CISA weekly bulletin lists several *other* code-projects Online Shoe Store CVEs from the same disclosure wave, which suggests a broadly insecure codebase rather than a one-off defect (CISA bulletin). |
noisgate verdict.
The decisive downward pressure is population reach: this is a niche code-projects sample app with very low expected enterprise deployment, not a broadly installed edge or infrastructure platform. The bug is real and the PoC is public, but absent KEV, mass exploitation, or wide installed base, it should not outrank mainstream internet-edge flaws in a 10,000-host queue.
Why this verdict
- Start from 6.3 MEDIUM: an exposed SQLi on a public product page is a legitimate application compromise path.
- Reachability cuts hard: attacker position is
unauthenticated remote, but that only matters if you actually run this obscure sample app; most enterprises do not, so exposed population is tiny compared with true patch-priority software. - The
PR:Lmetric likely understates exploitability on a vulnerable host: the PoC and code path suggest normal browse access to/details.php?id=, so I am *not* dropping this to IGNORE. - Blast radius is usually app-local: the reliable outcome is database compromise for this one application; turning SQLi into OS shell requires extra DB and filesystem privileges that many deployments will not have.
- Threat intel is quiet: no KEV listing, no authoritative active-exploitation evidence found, and the EPSS supplied is extremely low.
Why not higher?
Because this is not a common enterprise platform, the reachable victim population is the whole story. A pre-auth SQLi on a forgotten demo site can absolutely burn that site, but it does not create the kind of broad, repeatable fleet risk that justifies MEDIUM-to-HIGH prioritization across a large enterprise program.
Why not lower?
Because if you *do* have this app exposed, exploitation is not hypothetical. There is public PoC material, the vulnerable code pattern is straightforward, and a single internet-facing instance is enough for direct database compromise.
What to do — in priority order.
- Remove it from the internet — If this app exists, the best control is to stop treating a demo PHP storefront as public production software. Put it behind VPN, IP allowlists, or internal-only access; for a
LOWverdict there is no formal deadline, so handle as backlog hygiene unless the app is actually exposed. - Add a targeted WAF rule — Block obvious SQLi metacharacters and
sqlmap-style request patterns on/details.phpand especially theidparameter. This is a stopgap, not a fix, but it meaningfully raises attacker cost where no vendor patch exists; forLOW, treat this as opportunistic hardening rather than SLA work. - Constrain the database account — Strip dangerous DB privileges such as file-write or admin capabilities and keep the app user limited to only the tables and verbs it needs. This directly reduces the chance that SQLi becomes filesystem write or broader host compromise; again, no formal SLA at
LOW, but worth doing if the app must stay up. - Retire or replace the codebase — The surrounding disclosure pattern suggests a generally unsafe application, not a single isolated bug. If business value is real, migrate to a supported commerce platform; if not, decommission it as backlog hygiene.
EDR alonedoes not prevent SQL injection; it may help only if the attacker reaches shell or drops files.Patching PHP/MySQLdoes not fix application-layer string concatenation indetails.php.MFAis irrelevant if the vulnerable page is publicly reachable and does not require login.
Crowdsourced verification payload.
Run this on the target web host or against a checked-out application directory, not from an auditor workstation. Invoke it as python verify_cve_2025_0204.py /var/www/html/onl-shoe or python .\verify_cve_2025_0204.py C:\xampp\htdocs\onl-shoe; it needs only read access to the app files.
#!/usr/bin/env python3
"""
verify_cve_2025_0204.py
Static verifier for CVE-2025-0204 in code-projects Online Shoe Store 1.0.
Checks whether details.php appears to read $_GET['id'] and interpolate it
into the product query without prepared statements.
Exit codes:
0 = PATCHED
1 = VULNERABLE
2 = UNKNOWN
3 = USAGE ERROR
"""
import os
import re
import sys
from pathlib import Path
VULN_PATTERNS = [
re.compile(r"\$_GET\s*\[\s*['\"]id['\"]\s*\]", re.I),
re.compile(r"\$id\s*=\s*\$_GET\s*\[\s*['\"]id['\"]\s*\]", re.I),
re.compile(r"SELECT\s+\*\s+FROM\s+product\s+WHERE\s+product_id\s*=\s*['\"]\$id['\"]", re.I),
re.compile(r"query\s*\(\s*['\"].*product_id\s*=\s*['\"]\$id['\"]", re.I | re.S),
]
SAFE_HINTS = [
re.compile(r"prepare\s*\(", re.I),
re.compile(r"bind_param\s*\(", re.I),
re.compile(r"PDO\s*::\s*prepare", re.I),
re.compile(r"mysqli_prepare\s*\(", re.I),
re.compile(r"intval\s*\(\s*\$_GET\s*\[\s*['\"]id['\"]\s*\]\s*\)", re.I),
re.compile(r"filter_input\s*\(\s*INPUT_GET\s*,\s*['\"]id['\"]", re.I),
]
def load_file(base: Path):
candidates = [
base / "details.php",
base / "onl shoe" / "details.php",
base / "online shoe store" / "details.php",
]
for candidate in candidates:
if candidate.is_file():
try:
return candidate, candidate.read_text(encoding="utf-8", errors="ignore")
except Exception:
pass
found = list(base.rglob("details.php"))
for candidate in found:
if candidate.is_file():
try:
return candidate, candidate.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
return None, None
def main():
if len(sys.argv) != 2:
print("UNKNOWN")
print("Usage: python verify_cve_2025_0204.py <application_root>", file=sys.stderr)
sys.exit(3)
root = Path(sys.argv[1]).expanduser().resolve()
if not root.exists() or not root.is_dir():
print("UNKNOWN")
print(f"Path not found or not a directory: {root}", file=sys.stderr)
sys.exit(2)
target, content = load_file(root)
if not target or content is None:
print("UNKNOWN")
print("details.php not found under supplied root", file=sys.stderr)
sys.exit(2)
vuln_hits = sum(1 for p in VULN_PATTERNS if p.search(content))
safe_hits = sum(1 for p in SAFE_HINTS if p.search(content))
if vuln_hits >= 3 and safe_hits == 0:
print("VULNERABLE")
print(f"Matched vulnerable code pattern in: {target}")
sys.exit(1)
if safe_hits >= 1 and vuln_hits < 3:
print("PATCHED")
print(f"Found sanitization/prepared-statement indicators in: {target}")
sys.exit(0)
print("UNKNOWN")
print(f"Manual review needed for: {target}")
sys.exit(2)
if __name__ == "__main__":
main()
If you remember one thing.
LOW finding, so treat it as backlog hygiene. If the answer is yes, remove public exposure or add a WAF guardrail this sprint, then either retire the app or locally fix the SQLi in the next normal maintenance window, because there is no vendor-published fixed version in the reviewed sources.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.