This is a spare key hidden inside the manager’s office, not the front door left open
CVE-2025-0172 is an SQL injection in code-projects Chat System 1.0 inside /admin/deleteroom.php, where the id POST parameter is inserted into multiple DELETE queries without sanitization or parameterization. The public PoC shows a time-based blind payload against an authenticated session cookie, which means the issue is reachable over HTTP but only after the attacker can talk to the admin-side workflow. Affected versioning is narrow from what is publicly documented: Chat System 1.0; I found no authoritative vendor-fixed release.
The vendor's MEDIUM 6.3 is directionally closer to reality than the NVD's later 7.5 reinterpretation, but even 6.3 still overstates enterprise urgency once you account for real-world friction. This is a niche educational PHP/XAMPP app, not a common enterprise platform; the vulnerable endpoint lives under /admin/; and the exploit path assumes prior access plus a valid session. So yes, patch or retire it if you actually run it—but no, this should not outrank externally exposed pre-auth RCEs or mass-exploited edge bugs.
4 steps from start to impact.
Get a valid session
PHPSESSID. The product page says users must log in and that the app includes an admin panel, so an attacker needs either stolen credentials, a weak default/admin account, or some other foothold before this CVE matters.- Network reachability to the web app
- Valid user or admin credentials, or session theft
- Application is actually deployed and running
- This is not a pre-auth bug
- MFA, SSO wrapping, VPN-only access, or internal-only hosting can stop this before the CVE is even reachable
- Most enterprises do not deliberately deploy
code-projectseducational PHP apps at scale
Reach the admin delete-room action
/admin/deleteroom.php, an admin-side endpoint intended to delete chatrooms and related rows. The PoC uses a direct POST and same-origin headers, which is exactly the kind of request Burp Repeater or sqlmap can replay once the session is in hand.- Session has rights to hit
/admin/functionality or the app fails to enforce them correctly - Endpoint is not blocked by reverse proxy, VPN, or IP ACL
- The
/admin/path narrows reachable population further than a generic user-facing endpoint - If role checks are correctly enforced, basic users may not reach the delete workflow
id, but blind payloads often require tuned signatures.Exploit the SQL injection
$_POST['id'] flowing into three raw mysqli_query() DELETE statements. An attacker can use time-based blind SQLi such as id=4' or sleep(5)#&del=1 to confirm injection and then pivot to data extraction or destructive modification with tools like sqlmap.- Unsanitized vulnerable code is present
- Backend database functions like
SLEEP()are permitted - Attacker can send crafted POST bodies repeatedly
- Blind SQLi is slower and noisier than error-based SQLi
- Database privileges may limit impact
- Some WAFs or RASP controls will break stock payloads
/admin/deleteroom.php, abnormal response latency, SQL error traces, and DB slow-query entries tied to SLEEP() or suspicious predicates.Modify or dump application data
- Database account has meaningful read/write rights
- Sensitive data is stored in the same schema
- No segmentation exists between this app DB and more valuable systems
- Least-privileged DB accounts can cap what gets read or changed
- Lateral movement beyond this app still requires separate weaknesses
- These sample apps are often isolated or short-lived lab deployments
/admin/ — Put the admin path behind VPN, SSO, or IP allowlists so random internet traffic never reaches the vulnerable function. For a LOW verdict there is no mitigation SLA; treat this as backlog hygiene unless the app is externally exposed, in which case it is a cheap immediate hardening win./admin/deleteroom.php, especially payloads using quotes, comments, and timing functions. This is a compensating control, not a cure, and for LOW severity it can be rolled out during routine tuning rather than under an emergency deadline.- MFA alone does not fix the bug; it only makes the prerequisite session harder to obtain.
- Unauthenticated external vulnerability scans will often miss this because the endpoint sits behind login and likely behind admin navigation.
- EDR on the web server is weak coverage here because the exploit is SQL-layer abuse inside expected PHP/MySQL processes, not obvious malware execution.
The supporting signals.
| In-the-wild status | No evidence of active exploitation found in reviewed authoritative sources, and not listed in CISA KEV. |
|---|---|
| Public exploit / PoC | Yes. Public PoC by Sinon2003 on GitHub shows a time-based blind SQLi request against /admin/deleteroom.php using a live PHPSESSID. |
| EPSS | 0.0016 from the prompt input — very low predicted exploitation likelihood. I did not confirm an authoritative percentile from primary sources reviewed. |
| KEV status | No. CISA KEV catalog review did not show CVE-2025-0172. |
| CVSS disagreement | CNA/VulDB scored it 6.3 MEDIUM with PR:L; NVD later added 7.5 HIGH with PR:N. The public PoC includes a session cookie and the vulnerable path is under /admin/, so the authenticated/admin-side interpretation is more credible. |
| Affected versions | Publicly documented affected range is code-projects Chat System 1.0. |
| Fixed versions / backports | I found no vendor-published fixed version and no distro backport advisory. Treat this as no official patch identified. |
| Exposure / scanning reality | No reliable product-level Shodan/Censys fingerprinting evidence was found in reviewed sources. Based on the vendor page describing a free educational XAMPP/WAMP project, my inference is that enterprise internet exposure is low and highly incidental, not fleet-standard. |
| Disclosure timeline | Disclosed 2025-01-02; NVD shows last modification on 2025-04-03 when it added its own differing CVSS interpretation. |
| Reporter / source org | CVE source is VulDB; public exploit write-up is attributed to Sinon2003 on GitHub. |
Sources.
Why this verdict
- Start from 6.3, then subtract for attacker position: the best-supported path requires a valid session and reaches an
/admin/endpoint, which implies prior compromise, credential theft, or legitimate access before the CVE becomes usable. - Subtract again for exposed population:
code-projects Chat Systemis a free educational PHP/XAMPP package, so the fraction of real enterprise estates running it in production is tiny compared with mainstream SaaS, VPN, email, or edge software. - Do not add an exploitation premium: there is a public PoC, but no KEV listing, no cited campaign use, and EPSS is very low. Public code makes validation easy; it does not by itself make this a top-of-queue fleet emergency.
Why not higher?
If this were pre-auth on a user-facing route or a common enterprise product, the score would climb fast. But authenticated/admin-side reachability, uncertain role enforcement, and very low likely deployment scale compound downward pressure at every step of the chain.
Why not lower?
This is still genuine SQL injection, not a theoretical lint finding. If the app exists and the attacker can hit the endpoint, they can likely alter or extract application data, and the PoC means defenders should assume low-skill operators can reproduce it.
Crowdsourced verification payload.
Run this on the target web server or a source checkout that contains the application files. Invoke it as python3 verify_cve_2025_0172.py /var/www/html/chat-system or point it directly at admin/deleteroom.php; it only needs read access to the code, not root.
#!/usr/bin/env python3
# verify_cve_2025_0172.py
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
import os
import re
import sys
from pathlib import Path
VULN_FILE = os.path.join('admin', 'deleteroom.php')
def load_target(path_str):
p = Path(path_str)
if not p.exists():
return None, 'target path does not exist'
if p.is_dir():
target = p / VULN_FILE
if not target.exists():
return None, f'could not find {VULN_FILE} under directory'
return target, None
return p, None
def main():
if len(sys.argv) != 2:
print('UNKNOWN - usage: python3 verify_cve_2025_0172.py <app_dir_or_deleteroom.php>')
sys.exit(2)
target, err = load_target(sys.argv[1])
if err:
print(f'UNKNOWN - {err}')
sys.exit(2)
try:
data = target.read_text(encoding='utf-8', errors='ignore')
except Exception as e:
print(f'UNKNOWN - failed to read {target}: {e}')
sys.exit(2)
# Strong indicators of the published vulnerable code path
has_post_id = re.search(r"\$_POST\s*\[\s*['\"]id['\"]\s*\]", data) is not None
assigns_id = re.search(r"\$id\s*=\s*\$_POST\s*\[\s*['\"]id['\"]\s*\]", data) is not None
raw_delete_chatroom = re.search(r"delete\s+from\s+`?chatroom`?\s+where\s+chatroomid\s*=\s*'\$id'", data, re.IGNORECASE) is not None
raw_delete_chat = re.search(r"delete\s+from\s+`?chat`?\s+where\s+chatroomid\s*=\s*'\$id'", data, re.IGNORECASE) is not None
raw_delete_member = re.search(r"delete\s+from\s+`?chat_member`?\s+where\s+chatroomid\s*=\s*'\$id'", data, re.IGNORECASE) is not None
uses_mysqli_query = 'mysqli_query' in data
# Weak indicators of a local fix
prepared_stmt = any(token in data for token in [
'prepare(', 'mysqli_prepare(', 'bind_param(', 'PDO->prepare(', '->prepare('
])
numeric_cast = re.search(r"\$id\s*=\s*\(int\)\s*\$_POST\s*\[\s*['\"]id['\"]\s*\]", data) is not None
ctype_check = 'ctype_digit' in data or 'filter_var($id, FILTER_VALIDATE_INT)' in data
if has_post_id and assigns_id and uses_mysqli_query and raw_delete_chatroom and raw_delete_chat and raw_delete_member:
print(f'VULNERABLE - {target} matches the published SQLi pattern for CVE-2025-0172')
sys.exit(1)
if prepared_stmt or numeric_cast or ctype_check:
print(f'PATCHED - {target} does not match the published vulnerable pattern and shows signs of input hardening')
sys.exit(0)
print(f'UNKNOWN - {target} was found, but the code does not clearly match either the published vulnerable or patched pattern')
sys.exit(2)
if __name__ == '__main__':
main()