This is a loose floorboard behind the employee-only door, not a front-door breach
CVE-2025-0196 is a SQL injection in code-projects Point of Sales and Inventory Management System 1.0, specifically the cat parameter in /user/plist.php. The public PoC shows a crafted GET request to that route, and the CVE metadata assigns PR:L, which points to an authenticated low-privilege web user rather than anonymous internet access. Publicly documented affected scope is only version 1.0; no authoritative fixed release is referenced in the CVE, NVD, or OSV records reviewed.
The vendor/CNA MEDIUM rating is closer to reality than the word *critical* in the prose description. The decisive downgrade pressure is the attacker position: this is not pre-auth edge RCE, it is a low-privilege authenticated SQLi in a low-prevalence PHP demo-style application, with no KEV entry, very low EPSS, and no sourced evidence of broad in-the-wild abuse. If you actually expose this app to the internet, it still deserves attention; across a 10,000-host estate, it should not outrank broadly deployed pre-auth flaws.
4 steps from start to impact.
Get a valid application session
PR:L vector and the PoC's session cookie strongly suggest this is not meant to be exploited anonymously.- Target runs
code-projects Point of Sales and Inventory Management System 1.0 - Attacker can reach the web app over HTTP/HTTPS
- Attacker has a valid low-privilege login or hijacked session
- Requires prior access or valid credentials, which makes this post-initial-access in many real environments
- Many deployments keep small POS/admin apps internal or behind VPN/RDP jump paths instead of internet-exposed
- The affected product is niche and not common across enterprise fleets
Hit /user/plist.php with SQLi payloads using sqlmap or a browser
cat value to /user/plist.php; the public PoC demonstrates a classic boolean condition. Tools like sqlmap can automate detection, fingerprint the backend, and enumerate injectable parameters once the session cookie is supplied.- Authenticated route
/user/plist.phpis reachable - The backend still concatenates or unsafely handles
catin SQL - No effective WAF rule or custom filter blocks SQLi syntax
- The attacker needs the exact route and a working authenticated workflow
- WAFs, reverse proxies, or crude regex filters may disrupt commodity payloads
- Apps with integer coercion, patched code, or custom hardening break the public PoC quickly
cat; WAF/IDS may flag boolean-based payloads and comment markers.Enumerate and pull application data
- Injection is confirmed
- Database user has read and possibly write access to relevant tables
- Impact is bounded by the application's DB privileges
- Many small PHP apps use one schema and limited grants rather than dangerous server-wide DB privileges
- Encrypted or hashed secrets still need offline cracking or reuse to become useful
Attempt privilege expansion beyond the app
- DB user has elevated privileges or sensitive adjacent data is reachable
- Server-side hardening does not block file or command-adjacent abuse
- No evidence in the advisory or PoC shows reliable host-level RCE
- Modern least-privilege DB configurations usually block the nastier SQLi-to-RCE pivots
- EDR, file integrity monitoring, and DB audit controls are more likely to trip at this stage
The supporting signals.
| In-the-wild status | No authoritative exploitation evidence found in the sources reviewed. OpenCVE shows KEV: no, and neither NVD nor CVE references active campaign reporting. |
|---|---|
| Proof-of-concept availability | Public PoC exists from Masamune on GitHub Gist, published 2025-01-02, showing GET /POS_inventory/user/plist.php?cat=1%27%20or%201=1--%20- with a session cookie. |
| EPSS | User-supplied EPSS is 0.00086. OpenCVE currently displays roughly 0.00079, which is the same story operationally: extremely low near-term exploitation probability. |
| KEV status | Not KEV-listed in the reviewed aggregation data. That removes the biggest urgency amplifier for a medium-severity web bug. |
| CVSS vector and what it means | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L maps to network reachable, low complexity, but low privileges required. PR:L is the key friction point; this is not anonymous drive-by exploitation. |
| Affected versions | Public records tie the issue to code-projects Point of Sales and Inventory Management System 1.0 only, with CPE cpe:2.3:a:code-projects:point_of_sales_and_inventory_management_system:1.0:*:*:*:*:*:*:* in NVD. |
| Fixed version / backports | No vendor-fixed version, patch advisory, or distro backport was identified in the CVE, NVD, OSV, or product page references reviewed. Treat this as unsupported/unfixed until you verify your own code change. |
| Exposure reality | I found no reliable Shodan/Censys/FOFA population data tied specifically to this app. Practitioner inference: this is a low-prevalence, demo-style PHP project more often seen in labs, student deployments, or small internal systems than at enterprise internet edge. |
| Disclosure timeline | CVE record created 2025-01-03; NVD shows the record published 2025-01-03 and modified 2025-02-25. |
| Researcher / reporting org | The public PoC is attributed to Masamune. The CVE was assigned by VulDB. |
noisgate verdict.
The single biggest reason this lands in LOW is PR:L: the attacker needs an authenticated foothold in a niche application before the bug matters. That turns this from an edge-compromise candidate into a narrower post-login abuse path with limited evidence of real-world weaponization.
Why this verdict
- Downgrade for attacker position:
PR:Lmeans authenticated low-privilege access, which usually implies prior compromise, insider access, or valid business-user credentials before exploitation starts. - Downgrade for reachable population: this is a niche
code-projectsPHP application tied to version1.0, not a broadly deployed enterprise platform. Even if the bug is real, the exposed population is small. - Downgrade for threat evidence: no KEV listing, no sourced campaign reporting, and EPSS around
0.0008all argue against urgent fleet-wide action. - Partial upward pressure: public PoC exists and SQLi can expose or tamper with application data once a session is obtained, so this is not
IGNORE.
Why not higher?
There is no strong evidence this is anonymously exploitable at the internet edge, and there is no sourced evidence of widespread active exploitation. The blast radius is usually constrained to the application and its database privileges, with any host-level pivot depending on extra misconfigurations not demonstrated by the advisory.
Why not lower?
It is still a real injection flaw with a working public PoC, and authenticated SQLi against a business app can absolutely leak customer, product, or transaction data. If your environment actually runs this app and exposes it to users, you cannot dismiss it as noise.
What to do — in priority order.
- Restrict reachability — Put the application behind VPN, an allowlist, or a management jump path so random internet users cannot even attempt login or session theft. For a LOW verdict there is no SLA (treat as backlog hygiene), but if this app is internet-facing you should still reduce exposure during the next normal change window.
- Force authentication hygiene — Reset weak/shared app accounts, disable unused users, and enforce unique credentials so
PR:Lremains a real barrier instead of a paper wall. For LOW, handle this as backlog hygiene unless you know the app is externally reachable. - Add targeted WAF rules — Deploy explicit blocking or alerting for SQLi metacharacters and boolean/comment payloads on
/user/plist.phpand related/user/routes. This is compensating control, not a fix, and for LOW it fits standard maintenance rather than an emergency window. - Constrain DB privileges — Ensure the web app's database account cannot write files, create users, or access unrelated schemas; that sharply limits SQLi blast radius. For LOW, schedule this as hardening work in normal backlog flow.
- Retire or self-patch the app — Because no authoritative vendor-fixed version is published, the practical remediation is to remove the app, patch the vulnerable query yourself, or replace it with supported software. For LOW, plan that as hygiene work rather than a fire drill.
EDRalone does not stop SQL injection against a PHP app because the abuse happens inside normal web and database request flow.- Unauthenticated perimeter scans are weak coverage here; they often miss authenticated-only routes like
/user/plist.php. - Generic password rotation without reducing exposure or killing shared accounts does little if attackers can still obtain a valid low-privilege session.
- Relying on the vendor severity string or the word *critical* in the prose description does not reflect the real attacker position requirement.
Crowdsourced verification payload.
Run this on the target web server host that serves the PHP application, not from an auditor workstation. Invoke it as sudo bash verify-cve-2025-0196.sh /var/www/html/POS_inventory or let it search common docroots with sudo bash verify-cve-2025-0196.sh; read access to the PHP files is required, root is only needed if the web root is restricted.
#!/usr/bin/env bash
# verify-cve-2025-0196.sh
# Detect likely vulnerable code paths for CVE-2025-0196 in code-projects POS & Inventory 1.0
# Outputs exactly one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
TARGET_ROOT="${1:-}"
FOUND_ANY=0
FOUND_VULN=0
FOUND_PATCH_HINT=0
check_file() {
local f="$1"
local content
content="$(tr '\n' ' ' < "$f" 2>/dev/null)" || return
# Strong vulnerability hints: cat parameter from GET/request and direct SQL concatenation/interpolation.
if printf '%s' "$content" | grep -Eqi '\$_(GET|REQUEST)\s*\[\s*["'"'"']cat["'"'"']\s*\]' \
&& printf '%s' "$content" | grep -Eqi '(select|from|where).*(cat|category)' \
&& printf '%s' "$content" | grep -Eqi '(\.\s*\$cat\s*\.|\.\s*\$cat\s*[;)]|["'"'"']\s*\.\s*\$cat\s*\.\s*["'"'"']|where[^;]{0,120}\$cat)'; then
echo "VULNERABLE"
exit 1
fi
# Patch hints: explicit integer coercion or prepared statements around cat.
if printf '%s' "$content" | grep -Eqi '(intval\s*\(\s*\$_(GET|REQUEST)\s*\[\s*["'"'"']cat["'"'"']\s*\]\s*\)|\(int\)\s*\$_(GET|REQUEST)\s*\[\s*["'"'"']cat["'"'"']\s*\])'; then
FOUND_PATCH_HINT=1
return
fi
if printf '%s' "$content" | grep -Eqi '(prepare\s*\(|mysqli_prepare\s*\(|bind_param\s*\()' \
&& printf '%s' "$content" | grep -Eqi 'cat'; then
FOUND_PATCH_HINT=1
return
fi
}
scan_root() {
local root="$1"
[ -d "$root" ] || return
while IFS= read -r -d '' file; do
FOUND_ANY=1
check_file "$file"
done < <(find "$root" -type f -path '*/user/plist.php' -print0 2>/dev/null)
}
if [ -n "$TARGET_ROOT" ]; then
scan_root "$TARGET_ROOT"
else
for root in /var/www /srv/www /usr/local/apache2/htdocs /opt/lampp/htdocs /Applications/XAMPP/xamppfiles/htdocs; do
scan_root "$root"
done
fi
if [ "$FOUND_ANY" -eq 0 ]; then
echo "UNKNOWN"
exit 2
fi
if [ "$FOUND_PATCH_HINT" -eq 1 ]; then
echo "PATCHED"
exit 0
fi
echo "UNKNOWN"
exit 2
If you remember one thing.
code-projects app exists anywhere in your estate and whether any instance is internet-exposed; if yes, remove public reachability or add narrow compensating controls in the next routine change window. Because the reassessed verdict is LOW, there is no noisgate mitigation SLA and no noisgate remediation SLA beyond backlog hygiene; if you keep the app, schedule retirement or a local code fix as normal hardening work rather than emergency patching.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.