← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2025-0197 · CWE-74 · Disclosed 2025-01-03

A vulnerability classified as critical was found in code-projects Point of Sales and Inventory Management…

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a lockpick for a back-office door, not a battering ram for your perimeter

CVE-2025-0197 is an SQL injection flaw in code-projects Point of Sales and Inventory Management System affecting version 1.0, specifically the /user/search.php handler and its name parameter. The published PoC shows a crafted POST request against that endpoint, and both the CNA and NVD scoring indicate the attacker needs low privileges rather than being unauthenticated at the edge.

The vendor's MEDIUM label is technically reasonable in a vacuum, but it still overstates operational urgency for most enterprise patch queues. The decisive reality is friction: this is a niche PHP source-code project, commonly stood up in XAMPP-style lab deployments, and the exploit path starts after the attacker already has a valid session; that makes it a post-initial-access app bug with narrow real-world exposure, so I downgrade it to LOW for enterprise prioritization.

"This is authenticated SQLi in a niche demo-style PHP app, not an internet-scale emergency."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain a valid application session

The attacker first needs working credentials or a hijacked session for the POS application. The CVSS PR:L requirement and the PoC's use of a PHPSESSID cookie both point to an authenticated path, so this is not a blind perimeter smash. Common operator tooling here would be Burp Suite for session handling or stolen browser cookies after earlier compromise.
Conditions required:
  • Reachability to the web app over HTTP/HTTPS
  • Valid low-privilege account or captured session cookie
  • The target actually runs this specific code-projects app
Where this breaks in practice:
  • Requires prior compromise, credential theft, weak default creds, or exposed test instance
  • Many enterprises will not run this freeware app at all
  • MFA, VPN gating, or SSO fronting the app can block casual access
Detection/coverage: Web scanners may flag the app if fingerprinting succeeds, but authenticated DAST coverage is usually required. SIEM/WAF telemetry may show session creation followed by unusual POSTs to /user/search.php.
STEP 02

Send a crafted request to /user/search.php

Using Burp Repeater, curl, or sqlmap, the attacker submits a malicious name value to the search endpoint. The public PoC demonstrates a POST to the vulnerable page with the name parameter under attacker control.
Conditions required:
  • Authenticated access to the /user/ area
  • The endpoint is exposed and reachable
  • No server-side input handling that neutralizes the query
Where this breaks in practice:
  • Authenticated app crawling is brittle and often breaks in small custom PHP apps
  • Reverse proxies or WAF rules may normalize or block obvious SQLi payloads
  • Some deployments may have modified the source locally
Detection/coverage: Basic SQLi signatures are detectable by ModSecurity/CRS, commercial WAFs, or verbose Apache/PHP logs if request bodies are retained.
STEP 03

Exploit SQL injection to read or tamper with app data

Once injection lands, sqlmap or manual UNION/error-based techniques can enumerate tables, dump records, or alter inventory and user-related data in the application's backing database. The likely blast radius is the app's own database and the DB account's permissions, not instant host takeover.
Conditions required:
  • Injectable query path is still present in source
  • Database error handling or query behavior supports exploitation
  • The DB user has useful read/write permissions
Where this breaks in practice:
  • Least-privilege DB accounts can cap impact hard
  • Custom schema quirks often slow automated tooling
  • No evidence here of direct OS command execution from the SQLi alone
Detection/coverage: Database audit logs, WAF alerts, and anomalous query volume can expose enumeration or dump behavior. Coverage is weak if the app and DB are unmanaged lab assets.
STEP 04

Abuse recovered data for lateral business impact

The practical outcome is theft or manipulation of business records inside that POS instance: users, customers, products, suppliers, and sales data. An attacker can also weaponize harvested credentials if admins reused them elsewhere, but that is a secondary pivot, not the core vulnerability.
Conditions required:
  • Useful data exists in the app
  • Operators reused credentials or trust app data for downstream workflows
Where this breaks in practice:
  • Many deployments are demos, training systems, or isolated small-business installs
  • Enterprise identity stores are usually separate from this app
Detection/coverage: Look for abnormal searches, unexpected DB reads, and downstream account activity using credentials found in the app.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo evidence found that CVE-2025-0197 is in CISA KEV, and I found no public incident reporting tying this CVE to active campaigns during this review. Source: CISA KEV catalog
Public exploit / PoCYes. A public PoC was posted by Masamune on 2025-01-02 showing a crafted POST to /user/search.php with the name parameter. Source: GitHub Gist
EPSSUser-supplied EPSS is 0.00077 (~0.077%), which is very low threat forecasting signal. Third-party mirrors place it in the low percentile band rather than the hot path of likely exploitation. Background: FIRST EPSS
KEV statusNot listed in CISA Known Exploited Vulnerabilities as of this assessment. Source: CISA KEV catalog
CVSS and what it impliesCNA score is 6.3 MEDIUM with CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L, which matters because PR:L means the exploit chain starts after authentication. NVD later enriched a different vector, 6.5 MEDIUM, emphasizing confidentiality. Source: NVD
Affected versionsAuthoritative records only identify Point of Sales and Inventory Management System 1.0 as affected. Source: OSV record, OpenCVE mirror of CNA data
Fixed version / backportsI found no published fixed version and no distro backport references. Treat this as source-code abandonware until proven otherwise. Sources reviewed: code-projects product page, NVD
Exposure profileI found no GreyNoise, Censys, or vendor exposure report specific to this CVE. The product page itself describes a local XAMPP-style setup on localhost, which strongly suggests many installs are demos, labs, or small standalone deployments rather than hardened enterprise internet-facing apps; that is an inference from the installation guidance, not a census. Source: code-projects installation page
Disclosure timelineCVE published on 2025-01-03; the public PoC appears dated 2025-01-02. Sources: NVD, GitHub Gist
Researcher / reporting orgThe exploit write-up is credited to Masamune, while the CVE assignment/source authority is VulDB as CNA. Sources: GitHub Gist, OpenCVE CNA data
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.3/10)

The single biggest severity reducer is the authenticated access requirement: this bug does not give an attacker initial access, it rewards one they already have. Combine that with the product's niche, demo-style deployment profile and the absence of KEV or strong exploitation signals, and this falls out of the urgent enterprise patch lane.

HIGH Exploit path requires at least low privileges / a valid session
MEDIUM Real-world exposure is likely narrow because the app appears demo-style and niche
HIGH No public fixed version or backport was found

Why this verdict

  • Start from 6.3 MEDIUM: the vendor baseline is fair for raw technical impact because SQLi can expose or alter application data.
  • Authenticated remote access is required: PR:L means the attacker must already be inside the app. That is immediate downward pressure because it implies prior compromise, weak credential hygiene, or an exposed test account rather than direct perimeter break-in.
  • Reachable population is probably small: this is not Exchange, Confluence, or a mainstream ERP. It is a code-projects PHP source package typically installed in ad hoc XAMPP-style environments, so the fraction of large enterprises meaningfully exposed is low.
  • Blast radius is application-scoped: the likely win is the app database under whatever permissions that DB account has. There is no evidence in the advisory or PoC that this is a straight shot to host-level code execution.
  • Threat intel does not amplify urgency: there is a public PoC, but there is no KEV listing and the supplied EPSS is very low, so exploitation interest looks opportunistic rather than operationally widespread.

Why not higher?

If this were unauthenticated SQLi in a widely deployed enterprise product, this would stay in the MEDIUM-to-HIGH lane. But the chain here is narrowed twice: you need app access first, and the app itself has a small enterprise footprint. That combination kills urgency.

Why not lower?

I am not calling this IGNORE because it is still a real, weaponizable SQL injection with a public PoC. If your org actually runs this app in production and exposes it to users, a low-privileged insider or attacker with stolen creds can absolutely dump or tamper with business data.

05 · Compensating Control

What to do — in priority order.

  1. Remove public exposure — If this app is reachable from the internet, put it behind VPN, IP allowlisting, or retire the exposure entirely. For a LOW verdict there is no mitigation SLA; treat this as backlog hygiene, but if the app is public-facing do it immediately because exposure, not CVSS, is what makes this dangerous.
  2. Constrain authenticated access — Limit login to named admins, enforce strong auth upstream, and kill shared/default accounts. There is no mitigation SLA for LOW, so handle it in routine hardening, but this is the most effective way to raise friction because the exploit starts after login.
  3. Front it with SQLi-aware filtering — Deploy ModSecurity CRS or equivalent WAF rules for suspicious payloads hitting /user/search.php, especially the name POST field. This is not a substitute for code repair, but it is a practical guardrail when no vendor-fixed release is available.
  4. Audit the DB account permissions — Reduce the application's MySQL privileges to the minimum tables and operations it truly needs. That turns a successful injection into a smaller incident by capping read/write scope.
  5. Plan replacement or local code fix — Because no vendor patch was located, durable remediation is either decommissioning the app or editing the vulnerable PHP to use parameterized queries. For LOW, schedule it as backlog hygiene unless the instance handles sensitive data or is internet-accessible.
What doesn't work
  • Relying on EDR alone does not help much; this is a database-layer web request, not necessarily a malware execution event on the host.
  • A network IDS without HTTP body visibility will miss most of the useful signal, especially if the app is behind TLS.
  • Simply changing the server OS patch level does nothing for an application-layer SQL injection in PHP source code.
06 · Verification

Crowdsourced verification payload.

Run this on the target web server or in CI against the unpacked application source. Invoke it as python3 verify_cve_2025_0197.py /path/to/PISP or point directly at search.php; read access to the application files is sufficient, no admin privileges required unless your web root is restricted.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# verify_cve_2025_0197.py
# Heuristic verifier for CVE-2025-0197 in code-projects Point of Sales and Inventory Management System 1.0
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=USAGE

import os
import re
import sys

VULN_REL = os.path.join('user', 'search.php')

def read_file(path):
    try:
        with open(path, 'r', encoding='utf-8', errors='ignore') as f:
            return f.read()
    except Exception:
        return None

def locate_target(arg):
    if os.path.isfile(arg):
        return arg
    if os.path.isdir(arg):
        candidate = os.path.join(arg, VULN_REL)
        if os.path.isfile(candidate):
            return candidate
    return None

def main():
    if len(sys.argv) != 2:
        print('UNKNOWN')
        print('Usage: python3 verify_cve_2025_0197.py /path/to/project_or_search.php')
        sys.exit(3)

    target = locate_target(sys.argv[1])
    if not target:
        print('UNKNOWN')
        print('Could not locate user/search.php from supplied path')
        sys.exit(2)

    data = read_file(target)
    if data is None:
        print('UNKNOWN')
        print('Could not read target file')
        sys.exit(2)

    lower = data.lower()

    # Signals that suggest the vulnerable pattern:
    # 1) request parameter named 'name'
    # 2) SQL SELECT statement present
    # 3) concatenation/interpolation into query string
    # 4) no obvious prepared statement API in the file
    param_signal = bool(re.search(r"\$_(post|get|request)\s*\[\s*['\"]name['\"]\s*\]", data, re.I))
    select_signal = 'select' in lower and 'from' in lower
    concat_signal = bool(re.search(r"(select[\s\S]{0,300}(\.|concat\s*\(|\$[A-Za-z_][A-Za-z0-9_]*))", data, re.I))
    prepared_signal = any(x in lower for x in ['prepare(', 'bind_param(', 'pdo->prepare', 'mysqli_prepare'])

    # Strong vulnerable heuristic: tainted name parameter + query building + no prepared API
    if param_signal and select_signal and concat_signal and not prepared_signal:
        print('VULNERABLE')
        print(f'Heuristic match: {target} appears to use the name parameter in a dynamically built SQL query without prepared statements')
        sys.exit(1)

    # Strong patched heuristic: prepared statements present in the target file and the name parameter is handled
    if param_signal and prepared_signal:
        print('PATCHED')
        print(f'Prepared statement API detected in {target}; no obvious vulnerable pattern matched')
        sys.exit(0)

    print('UNKNOWN')
    print(f'File found at {target}, but the source pattern did not conclusively match vulnerable or patched logic')
    sys.exit(2)

if __name__ == '__main__':
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, first find out whether you even run this app: sweep web inventories, code repositories, and forgotten XAMPP/LAMP hosts for Point of Sales and Inventory Management System and /user/search.php. If you do not run it, close the ticket; if you do, remove any internet exposure and restrict access as hygiene, but this remains a LOW priority because it is authenticated, niche, and not backed by strong exploitation evidence. There is no noisgate mitigation SLA for a LOW verdict—treat it as backlog hygiene—and the noisgate remediation SLA is likewise backlog-oriented rather than date-driven; since no vendor-fixed version was found, remediation means retiring the app, carrying a local code fix, or permanently isolating it.

Sources

  1. NVD CVE-2025-0197
  2. GitHub Gist PoC by Masamune
  3. code-projects product / install page
  4. OSV record for CVE-2025-0197
  5. OpenCVE mirror of CNA data
  6. CISA Known Exploited Vulnerabilities Catalog
  7. FIRST EPSS
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.