Ir para o conteúdo

Blogue ·

Porque um scanner de vulnerabilidades deve enviar zero bytes

A fronteira entre uma verificação e um ataque são os bytes que põe na rede. Como tornar essa promessa num número que os testes reprovam, com as medições.

Por Provibr

Quem gere infraestrutura para outras pessoas mais tarde ou mais cedo quer saber se a porta 3306 numa das máquinas dos seus clientes está a responder à internet inteira. É uma pergunta razoável, o cliente quereria a resposta, e no momento em que se vai procurar passou-se a ser uma parte que envia tráfego não solicitado a uma máquina que está sob o contrato de outra pessoa.

O que separa isso de uma intrusão não é a intenção, e não é uma caixa nos termos de serviço. É o que saiu de facto do socket. Todo o resto é uma história sobre o que saiu do socket.

Construímos há pouco uma verificação de exposição no nosso agente, com uma regra que começou como uma frase num documento de desenho: não enviar consulta que altere nada, nem tentativa de autenticação, nem credencial por omissão, nem carga de exploração, nem recolha alargada de banners. Eis como essa frase se tornou uma coisa que um teste pode reprovar, e o que as sondas resultantes custam em bytes.

Uma promessa num comentário é uma promessa com prazo

O problema da frase acima não é ser difícil de cumprir. É ser fácil de cumprir durante uns seis meses.

Alguém acrescenta um EHLO à sonda de SMTP para conseguir detetar se é oferecido STARTTLS, o que é informação genuinamente útil. Os testes existentes continuam a passar, porque afirmam sobre o que a sonda encontrou e não sobre o que ela disse. A partir desse dia o software envia comandos de protocolo a máquinas de clientes, e o documento de desenho continua a dizer que não envia. Nada ficou vermelho. Nada alguma vez ficará.

Por isso transformámos a frase num número onde um número é possível. Cada socket que a verificação abre é embrulhado num fluxo que conta os bytes escritos, e o total viaja de volta com o resultado. Quatro dos seis tipos de sonda levam um valor exato afirmado nos testes: zero para as duas que não enviam nada, trinta e dois para SSH, oito para PostgreSQL. As outras duas não podem, porque um ClientHello e um negotiate de SMB variam de comprimento consoante o que é oferecido lá dentro; o seu limite é antes uma forma: uma única mensagem e nada a seguir. Acrescentar um EHLO a uma sonda afirmada em zero é agora um teste vermelho com um número lá dentro.

Dois pormenores desse contador acabaram por importar.

Conta escritas e não leituras. O que o outro lado oferece por vontade própria não é uma coisa que tenhamos causado; o que enviamos é. E é um contador partilhado em vez de um campo no nosso próprio tipo de fluxo, porque a sonda de TLS entrega o seu socket a uma biblioteca que depois escreve por cima os seus próprios registos de aperto de mão. Sem um contador partilhado, a única sonda que usa código de outra pessoa seria a única sonda por contar, que é precisamente onde um orçamento de bytes é mais difícil de raciocinar.

Quanto custa cada sonda

SondaO que enviamosO que é lido
Apenas abrirnada, afirmado em 0 bytesnada
Banner: FTP, Telnet, SMTP, MySQLnada, afirmado em 0 bytesuma saudação limitada
SSHuma linha de identificação, afirmada em 32 bytesa linha de identificação do servidor e, se a oferecer, a sua lista de algoritmos
TLSum ClientHello, de comprimento variávelo hello do servidor e o certificado
SMBum negotiate, de comprimento variávela resposta ao negotiate
PostgreSQLo pedido de SSL, afirmado em 8 bytesum byte

Nada se segue à abertura. Nenhuma segunda mensagem, nenhum keepalive, nenhuma conclusão de um aperto de mão. Assim que o outro lado falou, o socket fecha.

SSH: trinta e dois bytes, e porque não pode ir mais longe

O protocolo SSH faz os dois lados enviarem primeiro uma linha de identificação. A nossa é uma linha de trinta e dois bytes, e é a única coisa que a sonda escreve. Depois disso lê: a linha de identificação do servidor e, se o servidor enviar uma sem lhe ser pedida, a sua mensagem de troca de chaves com os algoritmos oferecidos lá dentro.

A parte importante é o que está ausente. A sonda nunca envia a sua própria mensagem de troca de chaves. Isso não é uma política, é um limite estrutural: sem ela a troca de chaves não pode prosseguir, nunca se estabelece sessão nenhuma, e não existe portanto estado no protocolo em que um pedido de autenticação pudesse ser enviado. «Nenhuma tentativa de autenticação» deixa de ser uma regra de que alguém se tem de lembrar.

A linha de identificação nomeia o produto em vez de imitar um cliente. Um administrador que leia o seu registo de autenticação deve conseguir ver quem se ligou. Uma cadeia neutra ou forjada faria uma verificação legítima parecer reconhecimento, o que é uma má troca pelos dois segundos de obscuridade que compra.

Há um custo, e vale a pena nomeá-lo porque aparece como um problema de qualidade de dados e não como um erro. Alguns servidores esperam pela mensagem de troca de chaves do cliente antes de enviarem a sua, e o protocolo permite qualquer das ordens. Quando isso acontece, a sonda fica com uma cadeia de versão e sem lista de algoritmos. A cobertura dessa porta é então parcial, e tem de ser registada como parcial. Se fosse registada como completa com uma lista vazia, o motor de regras concluiria que não são oferecidos algoritmos desatualizados, que é o pior resultado possível: um «seguro» confiante derivado de uma ausência de dados.

Os protocolos que falam primeiro, e a tentação de responder

FTP, Telnet, SMTP e MySQL cumprimentam todos quem se liga. A sonda para esses não envia nada de todo: ligar, ler um número limitado de bytes, fechar. Isso não é uma recolha de banners, porque não há maneira de abrir uma porta dessas sem receber a saudação, e nada foi pedido.

A tentação do EHLO é real e decidimos contra ela. Saber se um servidor de correio oferece STARTTLS é genuinamente valioso. Também exige enviar um comando de protocolo, e a regra era sobre factos que o outro lado entrega sem lhe ser pedido. A consequência é que uma constatação de SMTP fica com uma severidade mais baixa e uma confiança mais baixa do que teria de outro modo. É esse o preço honesto e deve estar visível na constatação em vez de ser afastado por argumentos.

O PostgreSQL é o caso intermédio interessante. Oito bytes é o pacote inteiro de pedido de SSL: um comprimento e um número mágico, que é a primeira coisa que qualquer cliente envia e que não é uma consulta, não é uma credencial e não é uma autenticação. O servidor responde com um único byte a dizer se vai falar TLS. Um byte de resposta chega para distinguir uma base de dados que exige cifra de uma que não exige, e não há versão desta verificação que envie menos.

Uma porta aberta não é uma vulnerabilidade

A porta 445 a responder não é o SMB1 estar ativo. São dois factos separados e precisam de dois campos separados.

A nossa sonda regista um estado para a porta, que é se está lá alguém, e no máximo uma peça de prova, que é o que essa pessoa disse. Um negotiate que volta sem um dialeto antigo deixa quem pergunta com uma porta aberta e mais nada, e isso é um resultado completo e não um resultado parcial. A tentação de juntar os dois numa única severidade é forte porque produz um painel muito mais entusiasmante.

A higiene das provas pertence ao mesmo parágrafo, porque uma saudação não é uma cadeia inofensiva. Os banners de FTP e de SMTP transportam na prática o nome de anfitrião do cliente, por vezes o nome de anfitrião do cliente dele, e ocasionalmente um caminho em disco. Guardá-los em bruto significa que a tabela de constatações se torna um sítio onde se acumula informação pessoal e estrutural sobre as redes de outras pessoas, retida durante tanto tempo quanto as constatações forem retidas, visível a qualquer pessoa que consiga ler uma constatação.

Portanto o que sai da sonda é um símbolo de protocolo normalizado, um fragmento de versão recortado por uma regra documentada, o número de bytes lidos e um resumo criptográfico dos bytes em bruto. O resumo torna duas análises comparáveis sem que ninguém guarde o texto. Essa última propriedade é a que faz falta a quem a saltar: sem ela, «isto mudou desde o mês passado» exige a coisa que se decidiu não guardar.

O sensor não tem opiniões

Mais uma separação, e é a que torna o resto sustentável.

O agente mede. Não resolve nomes de anfitrião, não guarda lista de portas própria e não escolhe alvos: o endereço e as portas são escritos pela plataforma, que verificou que o endereço está atualmente atribuído a essa organização e a esse servidor antes de os enviar. Sem alvos, o agente não mede nada.

O juízo acontece na plataforma, a partir de um conjunto de regras que pode ser lido e versionado. Isto importa porque uma constatação sobrevive ao código que a produziu. Daqui a seis meses alguém vai perguntar porque é que uma análise em setembro foi classificada como alta, e a única maneira de responder é ter as regras e as medições como coisas separadas, recuperáveis individualmente. Se a severidade fosse cozida no sensor, a resposta seria «porque aquela versão do agente achou que sim», o que não é uma resposta.

O mesmo raciocínio é a razão pela qual o agente se liga para fora e nunca está à escuta, e pela qual as credenciais ficam no anfitrião em vez de viajarem até nós. Um componente que só comunica o que mediu é um componente cujo raio de destruição se consegue descrever numa frase.

O que escreveríamos

  1. Transforme a promessa num número. Se a sua regra é sobre o que envia, conte o que envia e afirme sobre a contagem. Um comentário não pode reprovar.
  2. Prefira limites que sejam estruturais. Não enviar uma mensagem de troca de chaves significa que a autenticação é inalcançável, o que é mais forte do que uma regra a dizer para não autenticar.
  3. Deixe uma sonda ser parcial. Os dados em falta têm de ser visíveis como em falta, porque a alternativa é uma negativa confiante que ninguém consegue auditar.
  4. Mantenha «aberta» e «vulnerável» em campos diferentes, e faça o motor de regras combiná-los num sítio que se consiga ler.
  5. Não guarde banners em bruto. Normalize, resuma, e guarde o resumo para comparação.
  6. Ponha a opinião na plataforma, para que um juízo do trimestre passado continue explicável neste trimestre.

Para ser claro acerca do nosso próprio produto: isto é um detetor, está atrás de um interruptor ao nível da organização que está atualmente desligado, e não é uma coisa que se possa comprar hoje. As medições acima vêm da implementação e dos seus testes, não de uma página de marketing.

Construído para o Provibr, onde o agente corre dentro da rede do próprio cliente. O lado da verificação do mesmo desenho, provar que um nome de anfitrião pertence a quem o pede, está em como provar que um nome de anfitrião é seu.

Comece com um host e um agente

Crie uma conta, instale o agente com um único comando e ligue o seu primeiro host Proxmox. O período experimental dura 14 dias e não pede quaisquer dados de pagamento.