2 pontos por GN⁺ 2024-04-10 | 1 comentários | Compartilhar no WhatsApp
  • 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_keys e 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

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

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

 
GN⁺ 2024-04-10
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 :P

    • Olhando só para esse log, parece que Luciano estava gerando chaves em massa e achou estranho haver mais colisões do que o esperado
  • A 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

    • Vejo o caso xz como uma grande vitória do software open source
      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
    • Bugs também são descobertos o tempo todo em software de código fechado. Muitos deles podem ser encontrados mesmo sem o código
      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
    • Em código proprietário/fechado, as pessoas também encontram bugs de software o tempo todo
    • Não há discordância de que open source é melhor do que código fechado
      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

    • Na época, parecia que o Debian recebeu bastante crítica por esse bug, mas, como dito acima, houve uma tentativa de colaboração
      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
    • Em vez de azar, talvez tenha faltado cobertura de testes automatizados
      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

    • https://www.unciphered.com/blog/randstorm-you-cant-patch-a-h...
      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
    • Um problema desses provavelmente seria descoberto bem rápido
      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
    • https://news.ycombinator.com/item?id=6195493
    • O hack da Wintermute, de US$ 160 milhões, aconteceu por causa de geração insegura de chaves em uma biblioteca pública
      Mas, nesse caso, é improvável que isso tenha sido introduzido de propósito
    • Considerando que cada chave pode ser gerada deterministicamente a partir de uma seed key, e que a seed key não é infinita, no fim é uma questão de tempo
      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

    • Em sintaxe, isso é chamado de problema de anexação de sintagma preposicional
      É a questão de ler a frase como (investigar o problema) (com a equipe do GitHub) ou como investigar (o problema relacionado à equipe do GitHub)
      Lidar corretamente com isso é conhecido por ser algo bastante difícil
    • Dá para ler dos dois jeitos, mas se houvesse uma vírgula depois de “problem”, a ambiguidade teria desaparecido
  • 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?

    • Esse mal-entendido parece ser bem difundido. Mas, na prática, não foi isso que aconteceu
      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
    • Isso está errado. O OpenSSL também semeava o gerador de números aleatórios com dados lidos de /dev/urandom
  • 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

    • Devia haver muitas máquinas envolvidas, e normalmente é mais fácil manter um único banco de dados do que manter vários bancos
      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 p ou q em comum: https://factorable.net/weakkeys12.extended.pdf

  • Fico me perguntando se o GitHub ainda roda um openssh com patch

    • Se quiser, não é difícil ver algo bem próximo do código-fonte do GitHub
      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
    • No mínimo, eles não devem ter voltado a colocar todas as chaves em ~/.ssh/authorized_keys
    • O GitHub usa algo chamado babeld
      Se você se conectar por telnet à porta 22 de github.com, a string de versão aparece imediatamente
    • Em 2015, eles usavam libssh
      Corrigindo: primeiro eu disse golang, mas, ao verificar, quem usava golang era o Bitbucket
    • Desde o OpenSSH 6.2, lançado em 2013, existe AuthorizedKeysCommand, então não é necessário patch