
Detectar com segurança a bypass de autenticação do Veeam Service Provider Console CVE-2026-58073
Um detector seguro e não autenticado para as vulnerabilidades KB4893 no Veeam Service Provider Console (publicado em 2026-08-04). Ele responde a uma pergunta por alvo, antes de qualquer autenticação ou TLS: as correções da KB4893 estão presentes neste console?
O par principal é uma cadeia. CVE-2026-58073 (CVSS 9.5) permite que um peer de rede não autenticado se faça passar por um agente de gerenciamento conectado e receba o certificado real desse agente, porque o handshake do agente decide a autorização a partir do GUID que o peer escreveu no próprio certificado. CVE-2026-58072 (CVSS 9.0) é uma escrita arbitrária de arquivo alcançável quando você possui uma identidade de agente. Encadeadas, elas resultam em execução remota de código não autenticada no console que gerencia os backups de todos os tenants. O mesmo aviso também corrige CVE-2026-58071 (CVSS 8.2, API de appliance proxied como Portal Administrator) e CVE-2026-58067 (CVSS 8.7, DoS não autenticado por exaustão de memória). CVE-2026-58073 e CVE-2026-58072 foram reportadas à Veeam por meio do HackerOne; o aviso não nomeia o reporter.
Este script não tenta impersonação, não solicita um certificado e não escreve um arquivo. Ele lê a geração de protocolo anunciada pelo roteador e nada mais.
Sim. O detector foi projetado para uso em produção e avaliação:
Connector nomeando um receiver que não existirá. Nenhuma sessão TLS é negociada, nenhum
certificado é apresentado, e nunca é chamado.SaveFilesChannelHostProxy.m_multiplexers. Nenhum receiver é registrado, nenhum canal ou multiplexer é construído,
nenhum registro de agente é tocado. Um handshake do tipo Receiver registraria um nome; esta ferramenta
nunca envia um.ConnectionHub.log, cada uma carregando o nome do receiver bf-probe-<uuid4> para que um defensor possa
distinguir um scan de um ataque. As linhas exatas estão abaixo.VULNERABLE depois de provar que é um
VSPC ConnectionHub (veja abaixo), então um serviço TCP silencioso não pode ser confundido com um console
sem patch.Por alvo, a ferramenta abre duas conexões TCP e envia um handshake ConnectionHub em cada uma, nomeando
um receiver bf-probe-<uuid4> que não existirá.
Sob o padrão --transport auto, um alvo cujo transporte não é o implicado pela sua porta
custa uma conexão extra: a sonda de transporte errado é rejeitada durante o handshake, antes que qualquer
nome de receiver seja lido, e o transporte correto é então usado para ambas as sondas reais. Fixe
--transport direct ou --transport gateway para manter exatamente duas conexões — vale a pena se você
citou uma contagem de conexões em uma solicitação de mudança.
Estado alterado no servidor: nenhum. O caminho de código Connector realiza uma busca de dicionário em
ChannelHostProxy.m_multiplexers, falha e retorna um erro. Nenhum receiver é registrado, nenhum
multiplexer ou canal é criado, nenhuma sessão TLS é negociada, nenhum registro de agente é tocado. Esta
ferramenta nunca envia um handshake do tipo Receiver, que é o que registraria um nome.
As entradas de log são gravadas em
%ProgramData%\Veeam\Veeam Availability Console\Log\Server\ConnectionHub.log. Verbatim de um
ConnectionHub 9.2.1.33875 ao vivo, com timestamps e JSON de escopo removidos:
sonda 1 (versão 6), builds com e sem patch:
[INFO] ChannelHostProxy: Accept connection begin {"RemoteEndPoint":"<ip>:<port>","Line":"1"}
[INFO] ChannelHostProxy: Accept connection end {"RemoteEndPoint":"<ip>:<port>","Line":"2",...}
[WARN] ChannelHostProxy: Cannot connect transmitter. Requested receiver not found
(receiver name:bf-probe-<uuid>) {"RemoteEndPoint":"<ip>:<port>","Line":"3",...}
sonda 2 (versão 7), apenas builds com patch:
as mesmas três linhas
sonda 2 (versão 7), builds sem patch:
[INFO] ChannelHostProxy: Accept connection begin
[WARN] ChannelHostProxy: Handshake failed. Reason:Unsupported client version "7"
[INFO] ChannelHostProxy: Accept connection end
Duas conexões, seis linhas, nenhuma outra entrada e nenhuma mudança de estado — confirmado em um host ao vivo.
A string literal bf-probe- em ConnectionHub.log identifica o tráfego desta ferramenta, então um defensor
pode atribuí-lo e uma equipe de scan pode provar o que enviou. Altere RECEIVER_PREFIX no
código-fonte se precisar de um marcador diferente.
O roteador de agentes de gerenciamento ConnectionHub lê um handshake do cliente antes de qualquer autenticação
ou TLS, e Request.Read valida a versão de protocolo anunciada pelo cliente contra um intervalo fixo. A
correção ampliou esse intervalo no mesmo build que corrigiu as CVEs:
| Build | Verificação | Aceita |
|---|---|---|
<= 9.2.1.33875 (vulnerável) | (uint)(versionByte - 3) <= 3 | 3, 4, 5, 6 |
>= 9.3.0.35057 (com patch) | (uint)(versionByte - 3) <= 4 | 3, 4, 5, 6, 7 |
Portanto, um handshake anunciando a versão 7 é um discriminador binário limpo. O detector envia duas sondas por alvo, nesta ordem por um motivo (a detecção de transporte pode adicionar uma terceira — veja abaixo):
| Sonda | Anuncia | Propósito |
|---|---|---|
| 1 | versão 6 | Deve retornar Requested receiver not found, provando que o alvo realmente é um VSPC ConnectionHub |
| 2 | versão 7 | Uma resposta significa PATCHED; silêncio significa VULNERABLE |
Sem a barreira do estágio um, o silêncio na sonda 2 também corresponderia a qualquer serviço TCP silencioso na internet, e firewalls seriam reportados como consoles Veeam vulneráveis.
Funciona sobre ambos os caminhos que um agente de gerenciamento usa:
| Transporte | Porta | Exposição |
|---|---|---|
| Direto ao ConnectionHub | 9999 | geralmente interno |
| Através de um gateway Veeam Cloud Connect | 6180 | voltado à internet por design |
O caminho do gateway precisa de um prólogo de relay que o caminho direto não deve ter, então a sonda 1
também serve como detecção de transporte. Sob o padrão --transport auto, ele tenta um transporte e, se
a barreira de fingerprint não passar, tenta o outro. Qualquer um que passe é fixado, e a sonda 2 o
reutiliza — um arquivo de alvos misto não precisa de anotação por host.
A fixação é essencial. Se a sonda 2 pudesse tentar novamente no outro transporte, o silêncio não seria mais
atribuível à verificação de versão, apenas a "um dos dois caminhos de bytes não respondeu", que é como um
VULNERABLE falso é fabricado.
Qual transporte é tentado primeiro é decidido pela porta, e isso não é cosmético — as duas incompatibilidades falham em velocidades muito diferentes:
| Incompatibilidade | Como o lado remoto lê | Custo |
|---|---|---|
| Prólogo de relay → hub direto | meta int16 de hostType 44 / versionByte 0, falha na verificação de intervalo de Request.Read | descartado em uma ida e volta |
| Handshake direto → gateway | comprimento de frame int32 de 1,012,729,346 | o gateway espera por bytes que nunca chegam; queima o timeout completo |
Então auto lidera com o serviço que possui a porta: gateway primeiro em 6180, direto em todos os
outros lugares. Isso mantém o caso comum em uma única tentativa e a incompatibilidade cara fora do caminho
rápido. Uma sonda que falha ao abrir TCP completamente faz curto-circuito sem tentar o segundo transporte,
então hosts mortos em uma varredura ampla custam um timeout, não dois.
VULNERABLE significa "as correções da KB4893 não estão presentes", não "este é o 9.2.1.33875". Builds mais
antigos que o 9.2.1 compartilham a mesma verificação de versão, então devem reportar o protocolo 6 e ser
reportados como vulneráveis também (inferido do código, não medido — veja Limitações), mas a ferramenta
não pode separar 9.2.1 de 9.1 ou 8.1. Confirme o build exato na UI do console se precisar.
# host único (TCP/9999 padrão)
./cve_2026_58073_check.py vspc.example.com
# porta explícita, vários hosts
./cve_2026_58073_check.py vspc.example.com:9999 10.0.0.5
# escanear uma lista, um alvo por linha (comentários '#' permitidos), saída compacta
./cve_2026_58073_check.py -f targets.txt --brief
# saída legível por máquina para pipelines
./cve_2026_58073_check.py -f targets.txt --json > results.json
# um gateway Veeam Cloud Connect — o transporte de relay é detectado automaticamente
./cve_2026_58073_check.py cc-gw.example.com:6180
# fixar o transporte para pular a detecção (a porta então assume o padrão 6180)
./cve_2026_58073_check.py --transport gateway cc-gw.example.com
# validar os codecs de rede sem acesso à rede
./cve_2026_58073_check.py --self-test
| Flag | Descrição |
|---|---|
targets | Um ou mais HOST[:PORT] (a porta assume o padrão 9999, ou 6180 com --transport gateway) |
-f, --targets-file FILE | Ler alvos de um arquivo (um por linha; comentários #) |
--transport {auto,direct,gateway} | Como alcançar o ConnectionHub. auto (padrão) detecta por alvo; gateway adiciona o prólogo de relay do Cloud Connect e define a porta padrão como 6180 |
-p, --port PORT | Substituir a porta padrão |
--timeout SECS | Timeout por sonda (padrão: 8) |
--workers N | Alvos concorrentes (padrão: 16); a saída permanece na ordem de entrada |
-b, --brief | Uma única linha alinhada por alvo — ideal para escanear muitos hosts |
--json | Emitir JSON estruturado, incluindo cada sonda enviada por alvo |
--no-color | Desabilitar saída colorida (também respeita NO_COLOR e não-TTY) |
--self-test | Validar os codecs de rede .NET e sair; sem acesso à rede |
Um console sem patch (a saída padrão de duas linhas). O marcador [!] e VULNERABLE são renderizados
em vermelho em um TTY:
$ ./cve_2026_58073_check.py vspc.example.com
[!] vspc.example.com:9999: VULNERABLE [protocol-7-rejected]
ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)
Um console com patch:
$ ./cve_2026_58073_check.py patched.example.com
[+] patched.example.com:9999: PATCHED [protocol-7-accepted]
ConnectionHub accepts protocol 7, so the KB4893 fixes are present (>= 9.3.0.35057)
Um alvo de gateway, com o transporte de relay auto-detectado. O sufixo (gateway) nomeia o
transporte sobre o qual o veredito foi alcançado:
$ ./cve_2026_58073_check.py cc-gw.example.com:6180
[!] cc-gw.example.com:6180 (gateway): VULNERABLE [protocol-7-rejected]
ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)
Varrendo um ambiente, uma linha alinhada por host (--brief). O status de saída é 1 se qualquer
host for VULNERABLE, caso contrário 0 — útil em scripts:
$ ./cve_2026_58073_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE vspc.example.com:9999 protocol-7-rejected
PATCHED patched.example.com:9999 protocol-7-accepted
UNAFFECTED fileserver.example.com:9999 not-vspc
ERROR unused.example.com:9999 unreachable
exit: 1
Saída legível por máquina para pipelines (--json). Cada sonda é incluída por alvo, então uma
descoberta pode ser re-derivada das evidências em vez de confiada. transport é aquele sobre o qual o
veredito foi alcançado, e cada sonda carrega o transporte que usou — então um alvo auto-detectado mostra
a tentativa rejeitada também:
$ ./cve_2026_58073_check.py vspc.example.com --json
[
{
"target": "vspc.example.com:9999",
"host": "vspc.example.com",
"port": 9999,
"transport": "direct",
"verdict": "VULNERABLE",
"reason": "protocol-7-rejected",
"detail": "ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)",
"protocol_version": 6,
"affected_cves": [
"CVE-2026-58073",
"CVE-2026-58072",
"CVE-2026-58071",
"CVE-2026-58067"
],
"probes": [
{
"version_byte": 6,
"transport": "direct",
"connected": true,
"responded": true,
"status": "Error",
"message": "Cannot connect transmitter. Requested receiver not found (receiver name:bf-probe-b7c40be0-e2e8-41dc-9fc3-cbbd7345954a)",
"error": ""
},
{
"version_byte": 7,
"transport": "direct",
"connected": true,
"responded": false,
"status": "",
"message": "",
"error": ""
}
]
}
]
| Veredito | Tag de motivo | Significado |
|---|---|---|
VULNERABLE | protocol-7-rejected | VSPC ConnectionHub confirmado que aceita o protocolo 6 e rejeita o 7. As correções da KB4893 estão ausentes (<= 9.2.1.33875). |
PATCHED | protocol-7-accepted | VSPC ConnectionHub confirmado que aceita o protocolo 7. As correções da KB4893 estão presentes (>= 9.3.0.35057). |
UNAFFECTED | not-vspc | Aceitou TCP mas não respondeu a um handshake ConnectionHub válido em nenhum transporte tentado, então não é um VSPC ConnectionHub. |
INCONCLUSIVE | unexpected-reply | Respondeu à sonda de fingerprint com algo diferente de Requested receiver not found. |
INCONCLUSIVE | inconclusive-discriminator | Passou na barreira de fingerprint, mas respondeu à sonda de versão 7 de uma forma que não é nem aprovação nem falha — ou essa segunda conexão falhou completamente. Tente novamente. |
ERROR | unreachable | Não foi possível conectar, ou o gateway Cloud Connect recusou o prólogo de relay no primeiro transporte tentado (que sob auto significa qualquer alvo na porta 6180). |
| Código | Significado |
|---|---|
0 | Nenhum alvo era VULNERABLE |
1 | Pelo menos um alvo é VULNERABLE |
2 | Erro de uso (argumentos inválidos / arquivo de alvos ilegível) |
--transport auto; fixe
--transport direct para manter o caminho não testado fora de uma varredura completamente.VULNERABLE fala sobre o estado do patch, não sobre se alguém
explorou o console. A exploração deixa seus próprios rastros nos logs do console em builds com e sem
patch; procure por eles separadamente.Atualize para Veeam Service Provider Console 9.3.0.35057 ou posterior (KB4893). Todos os quatro problemas são corrigidos nesse único build, e não há backport para 9.2.x, então a remediação é uma atualização de versão, não um hotfix.
Duas coisas que a atualização não faz. Ela não restringe quem pode alcançar TCP/9999, que deve responder apenas às sub-redes onde seus agentes de gerenciamento vivem. E ela não revoga um certificado de agente que o console já emitiu, incluindo um emitido para um atacante enquanto estava sem patch. Se você encontrar evidências de exploração, abra um caso no Suporte Veeam para orientação sobre certificados de agente comprometidos: rotacioná-los não é um procedimento documentado, e os certificados que você pode gerenciar no portal não são a CA que assina certificados de agente.
Este código é distribuído sob uma licença MIT.
O uso desta ferramenta para atacar alvos sem consentimento mútuo prévio é ilegal. É responsabilidade do usuário final obedecer a todas as leis locais, estaduais e federais aplicáveis. Os desenvolvedores não assumem responsabilidade e não são responsáveis por qualquer uso indevido ou dano causado por este programa.