This is a sharp kitchen knife left in a back office, not a grenade in the lobby
CVE-2025-0208 is a SQL injection in code-projects Online Shoe Store 1.0, specifically summary.php via the tid parameter. The public write-up shows $_GET['tid'] flowing straight into a SQL query against the transaction table, which means a low-privileged user who can reach that page can likely read or alter application data; if the MySQL account is overprivileged, a deeper pivot is possible. The affected version range published by the CNA is only 1.0, and I could not find a vendor-fixed release or patch stream.
The vendor/CNA MEDIUM 6.3 is closer to reality than NVD's 9.8. The decisive issue is attacker position: the CNA scores this as PR:L, and the available exploit narrative lines up with an authenticated application flow rather than a clean unauthenticated edge exploit. Add the fact that this is a downloadable PHP project/demo app with uncertain enterprise footprint, no KEV listing, and a tiny EPSS, and this lands as LOW priority in a 10,000-host patch queue unless you knowingly run this app internet-facing.
4 steps from start to impact.
Get a valid session
PR:L, and the project page shows a normal login/sign-up flow, so the attacker likely needs to authenticate or at least reach a user-specific transaction summary path before the vulnerable parameter matters.- Application is deployed and reachable
- Attacker can register, authenticate, or steal a user session
- The vulnerable
summary.phpflow is exposed in that deployment
- This is not modeled as unauthenticated remote by the CNA
- Many scanners never complete sign-up/login/payment flows
- Some deployments may not expose real transaction history to ordinary users
Inject through tid
$_GET['tid'] assigned to $t_id and interpolated into a SQL statement without parameterization. Tools like sqlmap can probe summary.php?tid=... once provided the right session context, cookies, and request shape.- Attacker can send crafted requests to
/summary.php - Input reaches the database query unchanged
- WAF or app-layer filtering does not normalize/block payloads
- Request replay may need cookies, referer, and a valid transaction context
- Basic WAF signatures often catch commodity SQLi probes
- If
tidis server-side ownership-checked, horizontal reach may narrow
Enumerate or tamper with the database
sqlmap can automate enumeration and dumping if the DBMS and response behavior cooperate.- DB user has enough privileges for useful reads/writes
- Application error handling or response timing leaks enough signal
- The backend is a supported DBMS configuration
- Low-impact CVSS from the CNA implies partial rather than full compromise
- Least-privileged DB accounts can sharply limit what gets exposed
- Blind-only conditions make exploitation slower and noisier
Optional pivot to filesystem or code execution
sqlmap can reach OS-shell, but that is conditional, not baseline. That only becomes plausible if the database account has dangerous file/UDF privileges and the web stack permits writing or executing attacker-controlled content.- Overprivileged database account
- Writable webroot or DB-to-OS pivot path
- Server configuration allows execution of planted content
- Most real deployments fail here because DB users are not omnipotent
- This step is exactly why NVD's blanket
9.8looks overstated - EDR, AppArmor/SELinux, and locked-down filesystem permissions can break the chain
The supporting signals.
| In-the-wild status | No KEV listing found, and I found no public reporting of active campaigns tied to this CVE. CISA ADP metadata visible via OpenCVE marks exploitation as poc, Automatable: no, Technical Impact: partial. |
|---|---|
| Public PoC | Yes. A public GitHub gist by th4s1s dated 2025-01-02 shows the vulnerable code path and demonstrates sqlmap-style exploitation. |
| EPSS | User-supplied EPSS is 0.00096. Secondary trackers around this CVE place it in a low percentile band (~17-21%), which is consistent with weak attacker demand. |
| KEV status | Not listed in CISA's Known Exploited Vulnerabilities catalog. |
| CVSS disagreement | CNA/VulDB says 6.3 MEDIUM with PR:L; NVD shows 9.8 CRITICAL with PR:N. The public exploit narrative and project flow fit the CNA model much better than the NVD uplift. |
| Affected range | code-projects Online Shoe Store 1.0 only, vulnerable endpoint summary.php, parameter tid. |
| Fixed version | I found no vendor-fixed version and no formal patch advisory. For defenders, assume source remediation or compensating controls only unless you maintain a private fork. |
| Exposure reality | This is a downloadable PHP project, not a mainstream enterprise product. The download page shows 12,082 downloads, so installs exist, but I found no reliable Shodan/Censys-style fingerprint proving meaningful internet exposure at scale. |
| Disclosure | CNA timeline shows disclosure on 2025-01-03; NVD published on 2025-01-04. |
| Researcher / reporter | Reported as lio346 (VulDB User) in the CNA record. |
noisgate verdict.
The single biggest severity reducer is attacker position: this is not a clean unauthenticated internet-edge bug in the evidence we have; the CNA and PoC context both point to low-privileged application access first. On top of that, the affected software is a niche downloadable PHP project with weak signs of meaningful enterprise exposure, so the reachable population is small even before you consider exploitation quality.
Why this verdict
- Start from the CNA's 6.3, not NVD's 9.8 because the published exploit context and app flow support
PR:L, not a full unauthenticated edge compromise. - Authenticated or session-bound access is the governor: needing a valid user foothold implies either self-registration, stolen cookies, or prior access, which materially narrows who can reach exploit step one.
- The target population is narrow:
code-projectsapps are downloadable sample/demo PHP projects, not broadly deployed enterprise platforms, so the reachable blast radius across a 10,000-host estate is usually tiny. - Threat demand is weak: there is a public PoC, but there is no KEV listing, no campaign evidence I could find, and EPSS is extremely low.
- Impact is usually app-local: the realistic baseline is reading or tampering with this app's data; database-to-OS pivoting is conditional on extra misconfigurations and should not be baked into the base score.
Why not higher?
If this were clearly unauthenticated and broadly internet-exposed, SQL injection would deserve a much harder response. But the strongest available evidence points the other way: low-privileged access first, niche software, partial impact modeling, and no sign that attackers actually care.
Why not lower?
I am not calling this IGNORE because it is still a real SQL injection with public exploit guidance. If your org actually runs this app exposed to the internet, especially with open self-registration and a powerful DB account, the risk becomes immediately operational even if it does not justify front-of-queue treatment across the whole estate.
What to do — in priority order.
- Restrict access to
summary.php— Enforce authenticated access plus strict object ownership checks on transaction records so a logged-in user cannot request arbitrarytidvalues. For a LOW verdict there is no SLA; treat this as backlog hygiene and implement in the next normal application hardening cycle. - Block SQLi patterns on
tid— Add a targeted WAF or reverse-proxy rule forsummary.phpthat only allows the expected transaction-ID format and rejects metacharacters, comments, stacked queries, and time-delay payloads. There is no noisgate mitigation SLA for LOW; deploy during routine rule maintenance unless the app is internet-facing, in which case move faster. - De-privilege the database account — Remove dangerous MySQL privileges such as FILE, SUPER, and unnecessary write access from the application's DB user to keep a SQLi from turning into filesystem abuse or server takeover. With a LOW verdict this is backlog hygiene, but it materially reduces worst-case impact.
- Fix the query in source — Replace string interpolation with prepared statements or at minimum strict numeric casting/allowlisting for
tid. No vendor-fixed build was found, so plan to patch your maintained codebase in the next routine remediation cycle.
- MFA for administrators does not solve this if ordinary user access or self-registration is enough to hit the vulnerable endpoint.
- EDR on the web server does not stop the initial database exploitation; it only helps if the attacker later pivots to filesystem or process execution.
- Network segmentation alone does not help if the storefront is intentionally internet-facing and the vulnerable request is handled by the app itself.
Crowdsourced verification payload.
Run this on the target host or on a build artifact checkout that contains the PHP source. Invoke it with python3 check_cve_2025_0208.py /var/www/html/onl-shoe or point it directly at summary.php; it only needs read access to the source files.
#!/usr/bin/env python3
# check_cve_2025_0208.py
# Detect likely vulnerable code patterns for CVE-2025-0208 in code-projects Online Shoe Store 1.0.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import re
import sys
from pathlib import Path
VULN_GET_RE = re.compile(r"\$_GET\s*\[\s*['\"]tid['\"]\s*\]")
VULN_ASSIGN_RE = re.compile(r"\$\w+\s*=\s*\$_GET\s*\[\s*['\"]tid['\"]\s*\]\s*;")
VULN_QUERY_RE = re.compile(r"transaction_id\s*=\s*'\s*\$\w+\s*'", re.IGNORECASE)
SAFE_CAST_RE = re.compile(r"(intval\s*\(|\(int\)\s*\$_GET\s*\[\s*['\"]tid['\"]\s*\])", re.IGNORECASE)
PREPARED_RE = re.compile(r"(prepare\s*\(|bind_param\s*\(|PDO\s*::\s*prepare)", re.IGNORECASE)
def read_text(p: Path):
try:
return p.read_text(encoding='utf-8', errors='ignore')
except Exception:
return None
def candidate_files(target: Path):
if target.is_file():
return [target]
found = []
for p in target.rglob('summary.php'):
found.append(p)
return found
def assess_file(p: Path):
text = read_text(p)
if text is None:
return 'UNKNOWN', f'{p}: unreadable'
has_get = bool(VULN_GET_RE.search(text))
has_assign = bool(VULN_ASSIGN_RE.search(text))
has_query = bool(VULN_QUERY_RE.search(text))
has_safe_cast = bool(SAFE_CAST_RE.search(text))
has_prepared = bool(PREPARED_RE.search(text))
if has_get and has_query and not has_safe_cast and not has_prepared:
return 'VULNERABLE', f'{p}: raw tid parameter appears interpolated into SQL query'
if has_prepared or has_safe_cast:
return 'PATCHED', f'{p}: found parameterization or strict integer casting for tid'
if has_get or has_assign or has_query:
return 'UNKNOWN', f'{p}: suspicious markers found, but pattern does not conclusively match CVE-2025-0208'
return 'UNKNOWN', f'{p}: summary.php present, but expected markers were not found'
def main():
if len(sys.argv) != 2:
print('UNKNOWN - usage: python3 check_cve_2025_0208.py <path-to-app-or-summary.php>')
sys.exit(2)
target = Path(sys.argv[1])
if not target.exists():
print(f'UNKNOWN - target does not exist: {target}')
sys.exit(2)
files = candidate_files(target)
if not files:
print('UNKNOWN - no summary.php file found under target path')
sys.exit(2)
saw_patched = False
saw_unknown = False
messages = []
for f in files:
verdict, msg = assess_file(f)
messages.append(msg)
if verdict == 'VULNERABLE':
print('VULNERABLE - ' + ' | '.join(messages))
sys.exit(1)
if verdict == 'PATCHED':
saw_patched = True
if verdict == 'UNKNOWN':
saw_unknown = True
if saw_patched and not saw_unknown:
print('PATCHED - ' + ' | '.join(messages))
sys.exit(0)
if saw_patched and saw_unknown:
print('UNKNOWN - mixed results: ' + ' | '.join(messages))
sys.exit(2)
print('UNKNOWN - ' + ' | '.join(messages))
sys.exit(2)
if __name__ == '__main__':
main()
If you remember one thing.
LOW verdict and noisgate remediation SLA is effectively backlog hygiene, so go straight to routine source remediation and app hardening rather than emergency patch motion; in practice, put access restrictions/WAF tuning into the next normal change window and fix the code in your next planned maintenance release.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.