- Em 2008, um trabalho para corrigir o gargalo de login SSH do GitHub acabou revelando uma colisão anormal em que usuários diferentes tinham a mesma impressão digital de chave SSH
- Para evitar o problema de busca linear no arquivo
authorized_keys, que não parava de crescer, o GitHub modificou o OpenSSH para consultar a impressão digital da chave no MySQL - Depois da implantação do patch, surgiu um problema em que era possível acessar por SSH o repositório de outro usuário, mas colisões repetidas de impressões digitais de chaves eram difíceis de explicar como simples bug do patch
- Com a divulgação do DSA-1571-1 em 13 de maio de 2008, confirmou-se que o OpenSSL do Debian havia gerado chaves privadas previsíveis por cerca de 18 meses, reduzindo o número de chaves possíveis para pouco mais de 32.000 por usuário
- Grandes incidentes de segurança muitas vezes começam com pequenos sinais de que “tem algo estranho”, e a capacidade e o tempo para seguir essa pista até o fim fazem a diferença de verdade
O incidente que começou com o gargalo de login SSH do GitHub
- Em março de 2008, o autor, que trabalhava na Engine Yard, acabou ajudando o GitHub, então cliente da empresa de hospedagem focada em Rails, com um problema de desempenho no login via SSH
- O GitHub oferecia acesso a repositórios Git por meio de conexão SSH em
git@github.com, seguida de autenticação por chave pública - Na época, o gerenciamento de chaves dependia do método comum de usar o arquivo
~/.ssh/authorized_keys- Quando o SSH recebia uma solicitação de autenticação por chave pública, ele abria o arquivo
authorized_keyse fazia uma busca linear por uma entrada correspondente à chave enviada - Em contas comuns, com apenas algumas chaves, isso não era um grande problema, mas no GitHub, que crescia rapidamente, todas as chaves SSH se acumulavam em um único arquivo grande, e o tempo de login começou a ficar visivelmente mais lento
- Quando o SSH recebia uma solicitação de autenticação por chave pública, ele abria o arquivo
Patch no OpenSSH e consulta de chaves no MySQL
- Depois de analisar várias soluções, a equipe do GitHub e o autor decidiram modificar o OpenSSH para buscar a chave em um banco de dados MySQL com base na impressão digital da chave
- Essa não era uma mudança que pudesse ser feita de forma leviana
- Alterar o OpenSSH poderia ser desastroso do ponto de vista de segurança se algo saísse errado
- Como as outras opções eram piores, essa foi considerada a solução “menos ruim” disponível
- Uma parte considerável do trabalho de mudança foi dedicada a verificar que a segurança não seria comprometida
- Após a implantação no começo de abril de 2008, o login por SSH ficou mais rápido, e parecia que não seria preciso se preocupar com o mesmo problema por algum tempo
O sintoma aparentemente impossível das impressões digitais duplicadas
- No começo de maio de 2008, a equipe do GitHub enviou uma mensagem dizendo que alguns usuários conseguiam acessar, via SSH, os repositórios de outros usuários
- Como o problema estava diretamente ligado à autenticação por chave SSH e o patch no OpenSSH havia sido implantado pouco antes, o código escrito pelo autor se tornou o principal suspeito inicial
- Depois do processo de depuração, confirmou-se que dois usuários diferentes tinham a mesma impressão digital de chave
- Isso era algo praticamente impossível, a menos que os usuários tivessem compartilhado a mesma chave
- Os usuários afetados não se conheciam e responderam que nunca haviam divulgado suas chaves
- Depois, a mesma impressão digital foi encontrada em outro par de usuários, mas com um valor diferente do caso anterior
- Isso tornou difícil tratar o caso como mera coincidência isolada ou bug da aplicação web
- Depois de ficar suficientemente claro que o patch do OpenSSH não era a causa, o envolvimento direto do autor diminuiu
- Ele não era funcionário do GitHub e também precisava atender outros clientes da Engine Yard
- A equipe do GitHub continuou confirmando os casos com os usuários e percebeu que todos tinham em comum o fato de terem gerado suas chaves SSH em sistemas Debian ou Ubuntu
A causa revelada pela divulgação da vulnerabilidade no OpenSSL do Debian
- Em 13 de maio de 2008, a divulgação do DSA-1571-1 deixou a situação clara
- O pacote OpenSSL do Debian havia gerado chaves privadas previsíveis por cerca de 18 meses
- A causa foi que, durante uma limpeza no código de geração aleatória do OpenSSL, um mantenedor do Debian reduziu sem querer de forma drástica o espaço de chaves possíveis
- O número de chaves que um determinado usuário poderia gerar caiu de “um número absurdamente grande” para pouco mais de 32.000
- Como muitos usuários se cadastravam no GitHub, alguns provavelmente geraram novas chaves separadas, como era recomendado, e isso podia resultar em colisões
- Essa divulgação forneceu a prova decisiva de que o patch no OpenSSH do autor não era o culpado
Trabalhos posteriores relacionados às weak keys do Debian
- Mais tarde, o autor voltou a ter vários pontos de contato com as weak keys do Debian
- Ele opera o pwnedkeys.com, lidando com um grande repositório de chaves comprometidas conhecidas
- Também usou essas chaves para encontrar uma Certificate Authority com mau funcionamento
Como ter tempo para investigar o “estranho” fez a diferença
- O autor não conseguiu descobrir exatamente quando e como Luciano Bello identificou a vulnerabilidade que viria a receber o identificador CVE-2008-0166
- Como a versão estável do Debian com o código vulnerável havia sido lançada um ano antes da divulgação, pode ter havido tempo para notar que “tem algo estranho” ao ver colisões de chaves e investigar a fundo
- O backdoor recente no XZ também se conecta a um caso em que uma observação de que “tem algo estranho” levou a uma investigação intensa e à descoberta do problema
- O ponto importante é ter de fato a capacidade de realizar essa investigação aprofundada, além de tempo para isso
- Na época, o autor não conseguiu fazer pessoalmente uma investigação profunda
- A equipe do GitHub também estava ocupada com desenvolvimento de funcionalidades e resposta a incidentes em um serviço que crescia rapidamente
- O próprio autor também estava lidando com tickets de suporte na Engine Yard
- Grandes diferenças surgem quando, no momento certo, alguém com a técnica, o tempo e a energia consegue seguir a pista até o fim
1 comentários
Opiniões no Hacker News
Sobre o trecho “não consegui encontrar exatamente quando e como Luciano Bello descobriu a vulnerabilidade que mais tarde se tornaria a CVE-2008-0166”, os logs de IRC da época registram o seguinte:
17:23 < luciano> has really an accident. I was needing many primes numbers... 0:-)17:23 < Sesse> and you got the same numbers every time?17:25 < luciano> Sesse, not every time :PA frase “a indústria teve sorte de haver alguém com as habilidades, o tempo e a energia certos no momento certo” é um ponto em que dá para sentir, na prática, a estatística por trás de muitos olhos e de “a luz do sol é o melhor desinfetante”
Por mais improvável que pareça alguém passar por acaso e encontrar um bug, isso é possível, então acontece de fato
Em código proprietário/fechado, essa probabilidade é próxima de 0
Alguém percebeu algo estranho e, com o código-fonte, pôde verificar a situação real e ver que havia algo suspeito acontecendo
Especialistas de segurança das principais distribuições foram contatados para uma análise adicional e eles também confirmaram o problema de segurança, podendo agir imediatamente
Depois da divulgação pública, pessoas com expertise em várias áreas de software e segurança puderam investigar o que foi feito, como foi feito e quais eram os riscos
Commits suspeitos do mesmo desenvolvedor em outros softwares também foram rastreados e confirmados, e a análise do impacto continua
Cada distribuição ficou mais atenta aos detalhes de como a adulteração ocorreu em torno dos arquivos de build e começou a procurar formas de detectar e impedir casos semelhantes no futuro
Comparando com software de código fechado, é bem provável que relatos como “o software está um pouco lento” recebessem pouca atenção até que houvesse exploração real
Mesmo que a empresa acabasse descobrindo, provavelmente sairia apenas uma explicação muito cautelosa, revelando o mínimo de informação, o que prejudicaria bastante a capacidade de toda a indústria de evitar repetições
O problema é que é mais provável que não seja possível corrigi-los, ou que nada seja feito
A maioria das pessoas, ao encontrar um bug, não sabe o que fazer. Eu também era assim muito tempo atrás, e só depois percebi que coisas que eu tinha visto eram bugs
Os detalhes estão nebulosos porque foi há quase 30 anos, mas lembro que, mexendo no Microsoft NetMeeting no Windows, era possível provocar um crash com um erro de buffer overrun
Na época eu era iniciante em computadores e não entendia que um buffer overflow em uma aplicação de rede era algo muito ruim. Parece que muita gente que já estava há bastante tempo na indústria também não entendia
Naqueles tempos, reportar problemas de segurança também era muito mais difícil e, em alguns casos, até perigoso
No fim, são necessárias várias coisas: deparar-se com o problema, entender computação em profundidade suficiente para reconhecer que aquilo é ruim, ter um meio de reportar o bug em um lugar onde as pessoas olhem, e uma cultura de segurança que saiba quando e como tratar o relatório
Mas, ao ler a mesma frase, o que me perguntei foi quantos bugs de segurança graves como Heartbleed, CVE-2008-0166 e o caso xz estão acontecendo sem serem descobertos e divulgados
Um fato importante que só fiquei sabendo recentemente sobre essa vulnerabilidade é que essa alteração não foi algo feito às pressas
O mantenedor publicou na lista de e-mails do OpenSSL o problema que havia visto, pediu feedback, propôs uma correção e recebeu algumas respostas, inclusive do upstream
O resultado foi uma vulnerabilidade terrível, mas parece mais um caso de azar absurdamente grande, em que todos deixaram passar o problema
Além disso, o código upstream do OpenSSL estava invocando comportamento indefinido. Portanto, poderia ter sido válido um compilador fazer exatamente a mesma transformação que o mantenedor do Debian fez
Na época, isso parecia uma discussão acadêmica. Era difícil imaginar que um compilador seria tão perverso assim
Depois disso, passamos a entender melhor que comportamento indefinido deve ser evitado por completo
E, 8 anos depois, com a descoberta do Heartbleed, todos perceberam de repente o quanto o OpenSSL vinha sendo mal mantido
Em sua defesa, era um trabalho quase voluntário, e felizmente o financiamento posterior melhorou a situação
Para um código de gerador de números aleatórios crítico para segurança, parece realmente necessário haver um teste que gere uma quantidade enorme de números aleatórios e verifique se todos são únicos
Ao ler algo assim, fico me perguntando qual é a probabilidade de algo parecido já ter acontecido, ou ainda vir a acontecer, na função de geração de seed de uma das carteiras de hardware de Bitcoin populares
E também fico curioso sobre quais seriam as consequências
Nos últimos 22 meses, a Unciphered tem lidado com uma vulnerabilidade que afetou o BitcoinJS, amplamente usado na geração de carteiras de criptomoedas baseada em navegador, e produtos/projetos criados com esse software
Ao longo dos anos, essa vulnerabilidade levou à criação de um número considerável de carteiras de criptomoedas vulneráveis
No caso da vulnerabilidade de SSH, é preciso verificar ativamente se o servidor que se está tentando acessar tem uma das fingerprints ruins, mas no caso de carteiras isso permitiria acessar automaticamente, pela rede, os fundos de outras pessoas
Mas, nesse caso, é improvável que isso tenha sido introduzido de propósito
Com a tecnologia atual seriam necessários milhões de anos de computação, mas talvez não esteja fora do alcance de um ator estatal capaz de gastar uma quantia quase infinita de dinheiro para rodar esse volume de computação em poucas semanas
Pode chegar um momento em que qualquer pessoa que conheça o endereço consiga acessar todas as carteiras
Se você pode virar alvo de alguém com inteligência e dinheiro, Bitcoin não é tão seguro assim para guardar valor
Achei engraçada a frase “Ezra Zygmuntowitz me conectou ao GitHub e me deu tempo para investigar o problema a fundo com a equipe do GitHub”
Talvez por eu não ser falante nativo, também dá para ler como se significasse que havia um grande problema na própria equipe do GitHub, então achei que as frases seguintes fossem explorar isso
O trecho “fico imaginando quanto tempo levaria para ser descoberto se Luciano não tivesse encontrado” me parece algo que provavelmente só o GitHub, ou talvez um grande provedor de nuvem, teria encontrado por acaso
Porque não há muitos lugares que armazenem dezenas de milhares de chaves de usuários
É a questão de ler a frase como
(investigar o problema) (com a equipe do GitHub)ou comoinvestigar (o problema relacionado à equipe do GitHub)Lidar corretamente com isso é conhecido por ser algo bastante difícil
Pelo que entendi, o gerador de números aleatórios do OpenSSL era semeado com memória de stack não inicializada e o PID, e o Debian fez com que ele fosse semeado apenas com o PID
Mas, mesmo sem o patch do Debian, isso já não era bastante perigoso?
No código do OpenSSL havia dois pontos em que blocos de bytes eram copiados, e um deles podia copiar lixo não inicializado. Isso, de fato, estava errado
Alguém escreveu um patch para corrigir isso e, depois, sem ajuda de LLM, apenas com pura incompetência humana, alguém disse: “há outra cópia parecida ali perto, então esta também deve ser removida”
O Debian incluiu um patch com as duas alterações
Como resultado, o OpenSSL passou a não copiar byte nenhum
É bom não copiar dados não inicializados, mas ele também deixou de copiar entropia realmente aleatória para o pool. Putz
No trecho “Depois de considerar várias soluções possíveis, concluímos que a opção menos ruim era aplicar um patch no OpenSSH para que ele consultasse as chaves em um banco de dados MySQL indexado pela fingerprint da chave”, por que MySQL e não sqlite?
A situação era tentar acelerar o acesso a ~/.ssh/authorized_keys, e esse é exatamente o tipo de caso para o qual o MySQL foi projetado para brilhar
Parece que teria dado menos trabalho aplicar um patch no OpenSSH para verificar ~/.ssh/authorized_keys.db do que para fazê-lo usar MySQL
Também é bem provável que o MySQL já estivesse em operação. Nesse caso, não haveria custo inicial para armazenar os dados lá
De qualquer forma, o banco de dados de usuários provavelmente já existia em algum lugar
Independentemente da descoberta de um pequeno número de chaves fracas, é interessante que logins SSH lentos sejam uma pista que valha a pena puxar por vários motivos
Outro episódio interessante é o caso em que usaram o máximo divisor comum para detectar chaves RSA que tinham um fator
pouqem comum: https://factorable.net/weakkeys12.extended.pdfFico me perguntando se o GitHub ainda roda um openssh com patch
Basta comprar uma cópia do GitHub Enterprise, desfazer a ofuscação dos arquivos e dar uma olhada. Desofuscar é um desafio divertido e nem tão difícil
Infelizmente, como não é open source, não dá para compartilhar o código, falar sobre ele ou criar links para ele no GitHub
Ainda assim, se o GitHub Enterprise ainda usa esse patch, é bem provável que o GitHub em produção também use
~/.ssh/authorized_keysSe você se conectar por telnet à porta 22 de
github.com, a string de versão aparece imediatamenteCorrigindo: primeiro eu disse golang, mas, ao verificar, quem usava golang era o Bitbucket