
PRNG previsível do Debian OpenSSL (CVE-2008-0166)
URL original: http://metasploit.com/users/hdm/tools/debian-openssl/ (Espelho)
Exploit:
Ferramenta Recomendada: Crowbar (capaz de realizar força bruta em chaves SSH)
Método de Teste: ssh-vulnkey & dowkd.pl
CVE (CVE-2008-0166):
Em 13 de maio de 2008, o projeto Debian anunciou que Luciano Bello encontrou uma vulnerabilidade interessante no pacote OpenSSL que eles distribuíam. O bug em questão foi causado pela remoção das seguintes linhas de código do md_rand.c
MD_Update(&m,buf,j);
[ .. ]
MD_Update(&m,buf,j); /* purify complains */
Essas linhas foram removidas porque faziam com que as ferramentas Valgrind e Purify produzissem avisos sobre o uso de dados não inicializados em qualquer código vinculado ao OpenSSL. Você pode ver um desses relatórios enviados à equipe do OpenSSL aqui. Remover esse código teve o efeito colateral de prejudicar o processo de semeadura (seeding) do PRNG do OpenSSL. Em vez de misturar dados aleatórios na semente inicial, o único valor "aleatório" usado era o ID do processo atual. Na plataforma Linux, o ID máximo padrão de processo é 32.768, resultando em um número muito pequeno de valores de semente usados para todas as operações do PRNG.
Todas as chaves SSL e SSH geradas em sistemas baseados em Debian (Ubuntu, Kubuntu, etc.) entre setembro de 2006 e 13 de maio de 2008 podem estar afetadas. No caso das chaves SSL, todos os certificados gerados precisarão ser recriados e enviados à Autoridade Certificadora para assinatura. Quaisquer chaves de Autoridade Certificadora geradas em um sistema baseado em Debian precisarão ser regeneradas e revogadas. Todos os administradores de sistema que permitem que usuários acessem seus servidores via SSH com autenticação por chave pública precisam auditar essas chaves para verificar se alguma delas foi criada em um sistema vulnerável. Quaisquer ferramentas que dependiam do PRNG do OpenSSL para proteger os dados que transmitiam podem estar vulneráveis a um ataque offline. Qualquer servidor SSH que use uma chave de host gerada por um sistema defeituoso está sujeito à descriptografia de tráfego, e um ataque man-in-the-middle seria invisível para os usuários. Essa falha é desagradável porque até mesmo sistemas que não usam o software Debian precisam ser auditados, caso esteja sendo usada alguma chave criada em um sistema Debian. Os projetos Debian e Ubuntu lançaram um conjunto de ferramentas para identificar chaves vulneráveis. Você pode encontrá-las listadas na seção de referências abaixo.
As listas negras publicadas pelo Debian e pelo Ubuntu demonstram exatamente como o espaço de chaves é pequeno. Ao criar uma nova chave OpenSSH, existem apenas 32.767 resultados possíveis para uma determinada arquitetura, tamanho de chave e tipo de chave. A razão é que o único dado "aleatório" usado pelo PRNG é o ID do processo. Para gerar as chaves reais que correspondem a essas listas negras, precisamos de um sistema contendo os binários corretos para a plataforma alvo e uma maneira de gerar chaves com um ID de processo específico. Para resolver o problema do ID de processo, escrevi uma biblioteca compartilhada que pode ser pré-carregada e que retorna um valor especificado pelo usuário para a chamada getpid() da libc.
O próximo passo foi construir um ambiente chroot que contivesse os binários e bibliotecas reais de um sistema vulnerável. Tirei um snapshot de um sistema Ubuntu na rede local. Você pode encontrar o ambiente chroot completo aqui. Para gerar uma chave OpenSSH com um tipo, tamanho de bits e ID de processo específicos, escrevi um script de shell que poderia ser executado dentro do ambiente chroot. Você pode encontrar esse script de shell aqui. Este script é colocado no diretório raiz do sistema de arquivos Ubuntu extraído. Para gerar uma chave, este script é chamado com a seguinte linha de comando:
# chroot ubunturoot /dokeygen.sh 1 -t dsa -b 1024 -f /tmp/dsa_1024_1
Isso gerará uma nova chave DSA OpenSSH de 1024 bits com o valor de getpid() sempre retornando o número "1". Agora temos nossa primeira chave SSH pré-gerada. Se continuarmos esse processo para todos os PIDs até 32.767 e depois repetirmos para chaves RSA de 2048 bits, teremos coberto os intervalos de chaves válidos para sistemas x86 executando a versão com bug da biblioteca OpenSSL. Com esse conjunto de chaves, podemos comprometer qualquer conta de usuário que tenha uma chave vulnerável listada no arquivo authorized_keys. Esse conjunto de chaves também é útil para descriptografar uma sessão SSH previamente capturada, se o servidor SSH estiver usando uma chave de host vulnerável. Links para os conjuntos de chaves pré-geradas para chaves DSA de 1024 bits e RSA de 2048 bits (x86) são fornecidos na seção de downloads abaixo.
O interessante sobre essas chaves é como elas estão vinculadas ao ID do processo. Como a maioria dos sistemas baseados em Debian usa valores sequenciais de ID de processo (incrementando desde a inicialização do sistema e voltando ao início conforme necessário), o ID de processo de uma determinada chave também pode indicar quanto tempo após a inicialização do sistema essa chave foi gerada. Se olharmos o inverso disso, podemos determinar quais chaves usar durante um ataque de força bruta com base no alvo que estamos atacando. Ao tentar adivinhar uma chave gerada na inicialização (como uma chave de host SSH), as chaves com valores de PID menores que 200 seriam as melhores opções para um ataque de força bruta. Ao atacar uma chave gerada pelo usuário, podemos assumir que a maioria das chaves de usuário válidas foi criada com um ID de processo maior que 500 e menor que 10.000. Essa otimização pode acelerar significativamente um ataque de força bruta em uma conta de usuário remota através do protocolo SSH.
No futuro próximo, este site será atualizado para incluir uma ferramenta de força bruta que pode ser usada para obter rapidamente acesso a qualquer conta SSH que permita autenticação por chave pública usando uma chave vulnerável. As chaves nos arquivos de dados abaixo usam a seguinte convenção de nomenclatura:
/ Algorithm / Bits / Fingerprint-ProcessID
and
/ Algorithm / Bits / Fingerprint-ProcessID.pub
Para obter o arquivo de chave privada de qualquer chave pública, você precisa conhecer a impressão digital (fingerprint) da chave. A maneira mais fácil de obter essa impressão digital é através do seguinte comando:
$ ssh-keygen -l -f targetkey.pub
2048 c6:7b:14:fa:ae:b6:89:e6:67:17:ee:04:17:b0:ec:4e targetkey.pub
Se olharmos a chave pública em um editor, também podemos inferir que o tipo de chave é RSA. Para localizar a chave privada dessa chave pública, precisamos extrair os arquivos de dados e procurar por um arquivo chamado:
rsa/2048/**c67b14faaeb689e66717ee0417b0ec4e-26670**
No exemplo acima, a impressão digital é representada em hexadecimal com os dois-pontos removidos, e o ID do processo é indicado como "26670". Se quisermos autenticar em um sistema vulnerável que usa essa chave pública para autenticação, executaríamos o seguinte comando:
$ ssh -i rsa/2048/c67b14faaeb689e66717ee0417b0ec4e-26670 root@targetmachine
P: Quanto tempo levou para gerar essas chaves?
R: Usei 31 núcleos Xeon com clock de 2,33 GHz. Levei duas horas para gerar as chaves DSA de 1024 bits e RSA de 2048 bits para x86. As chaves RSA de 4096 bits levaram cerca de 6 horas para serem geradas. A geração das chaves RSA de 8192 bits levaria cerca de 100 horas no ritmo atual e provavelmente será interrompida antes da conclusão.
P: Você vai compartilhar seu código para distribuir a geração de chaves entre vários processadores?
R: Não. O código é hardcoded para esse cluster específico e é mal escrito demais para valer a pena limpá-lo.
P: Quanto tempo leva para quebrar uma conta de usuário SSH usando essas chaves?
R: Isso depende da velocidade da rede e da configuração do servidor SSH. Deve ser possível testar todas as 32.767 chaves de DSA-1024 e RSA-2048 em algumas horas, mas cuidado com scripts anti-força-bruta no servidor alvo.
P: Eu uso chaves RSA de 16384 bits, elas podem ser quebradas?
R: Sim, é apenas uma questão de tempo e poder de processamento. O conjunto de chaves RSA de 8192 bits levaria cerca de 3.100 horas de CPU para gerar todas as 32.767 chaves (100 horas nos 31 núcleos que estou usando agora). Imagino que o conjunto de chaves RSA de 16384 bits levaria algo próximo de 100.000 horas de CPU. Uma coisa a ter em mente é que a maioria das chaves está dentro de um intervalo muito menor, com base na semente do ID de processo, e não seria necessário gerar o conjunto inteiro para cobrir a maioria das chaves de usuário (a maioria das chaves está dentro dos primeiros 3.000 IDs de processo).
Copyright © 2008 H D Moore