Lemos muitas histórias tristes sobre comunidades que foram fatalmente comprometidas ou destruídas devido a explorações de segurança. Levamos essa lição a sério quando fundamos a Discurso nos esforçamos para criar software de código aberto que seja seguro e protegido para as comunidades por padrão, mesmo que haja milhares ou milhões delas por aí.
No entanto, também valorizamos a portabilidadeA portabilidade é a capacidade de colocar seus dados dentro e fora do Discourse à vontade. É por isso que o Discourse, diferentemente de outros softwares de fórum, usa por padrão uma licença Creative Commons. Como usuário básico em qualquer Discourse, o senhor pode facilmente exportar e baixar todas as suas mensagens diretamente de sua página de usuário.
Como proprietário de um site, o senhor pode fazer backup e restaurar facilmente todo o banco de dados do site a partir do painel de administração, diretamente no navegador da Web. Os backups semanais automatizados também são configurados para o senhor imediatamente. Não estou o maior especialista do mundo em backups para nada, senhor!
Ao longo dos anos, aprendemos que o equilíbrio entre segurança e portabilidade de dados pode ser complicado. O senhor pode apostar seu doce ASCII a download completo do banco de dados é o objetivo dos hackers a partir do momento em que eles ganham qualquer tipo de posição no seu sistema. É o prêmio final.
Para atenuar essa ameaça, temos restringido lentamente as restrições aos backups do Discourse de várias maneiras:
-
Os administradores têm uma senha com comprimento mínimo de 15 caracteres.
-
As ações do administrador de criação e download de backups são formalmente registradas.
-
Os tokens de download de backup são de uso único e enviados por e-mail para o endereço do administrador, para confirmar que o usuário tem controle total sobre o endereço de e-mail.
O nome do jogo da segurança é defesa em profundidade, portanto, todas essas etapas de fortalecimento ajudam… mas ainda precisamos presumir que os vilões da Internet conseguirão, de alguma forma, uma cópia do seu banco de dados. E depois? Bem, o que há no banco de dados?
-
Cookies de identidade
Os cookies são, obviamente, a forma como o navegador pode dizer quem é o usuário. Os cookies geralmente são armazenados como hashes, em vez do valor real do cookie, portanto, ter o hash não permite que o usuário se faça passar pelo usuário-alvo. Além disso, a maioria das estruturas modernas da Web faz um ciclo rápido de cookies, de modo que eles só são válidos por um breve período de 10 a 15 minutos.
-
Endereços de e-mail
Embora os usuários tenham motivos para se preocupar com a exposição de seus e-mails, muito poucas pessoas tratam seus endereços de e-mail como algo particularmente precioso atualmente.
-
Todas as postagens e conteúdo do tópico
Vamos supor, para fins de argumentação, que esse é um site totalmente público e que ninguém estava postando nada particularmente sensível nele. Portanto, não estamos preocupados, pelo menos por enquanto, com a revelação de segredos comerciais ou outras informações privilegiadas, já que todas as postagens eram públicas. Se estivéssemos, essa seria uma outra postagem do blog que eu poderia escrever mais tarde.
-
Hashes de senha
O que resta é os hashes de senha. E isso é … um problema sério, de fato.
Agora que o invasor tem seu banco de dados, ele pode quebrar seus hashes de senha com ataques off-line em grande escala, usando todos os recursos de qualquer nuvem que puderem pagar. E depois de decifrarem um hash de senha específico, eles poderão fazer login como esse usuário … para sempre. Ou, pelo menos, até que o usuário altere sua senha.
⚠️ É por isso que, se o senhor sabe (ou mesmo suspeita!) que seu banco de dados foi exposto, a primeira coisa que deve fazer é redefinir a senha de todos.
Mas e se o senhor não sabe? O senhor deve redefinir preventivamente a senha de todos a cada 30 dias, como os piores departamentos de TI das grandes empresas do mundo? Isso é totalmente hostil ao usuário e leva a patologias graves por si só. A realidade é que o senhor provavelmente não vai saberá quando seu banco de dados foi exposto, pelo menos não até que seja tarde demais para fazer algo a respeito. Portanto, é fundamental desacelerar os invasores, para que o senhor tenha tempo de lidar com isso e reagir.
Portanto, a única proteção real que o senhor pode oferecer aos seus usuários é a resistência a ataques dos hashes de senha armazenados. Há dois fatores que influenciam a força do hash da senha:
-
O algoritmo de hashing. O mais lento possível, e idealmente projetado para ser especialmente lento em GPUs por motivos que se tornarão dolorosamente óbvios daqui a cinco parágrafos.
-
O fator trabalho ou número de iterações. Defina esse número o mais alto possível, sem se expor a um possível ataque de negação de serviço.
Vi orientações que diziam que o senhor deveria definir o fator de trabalho geral alto o suficiente para que o hashing de uma senha levasse pelo menos 8 ms na plataforma de destino. Acontece que Sam Saffron, um dos meus cofundadores do Discourse, fez uma boa escolha em 2013 quando selecionou a recomendação do NIST de PBKDF2-HMAC-SHA256 e 64 mil iterações. Medimos e, de fato, isso leva cerca de 8 ms usando nosso código de login Ruby existente em nossos servidores atuais (bastante avançados, Skylake 4.0 Ghz).
Mas isso foi há 4 anos. Qual é exatamente a segurança dos hashes de senha no banco de dados hoje? Ou daqui a 4 anos, ou daqui a 10 anos? Estamos criando software de código aberto para o longo prazo e precisamos ter certeza de que estamos tomando decisões razoáveis que protejam a todos. Portanto, no espírito do projetando para o malÉ hora de colocar nosso capacete de Darth e bancar o vilão – o vamos quebrar nossos próprios hashes!
Vamos usar a maior e pior GPU que existe no momento, a GTX 1080 Ti. Como ponto de referência, para PBKDF2-HMAC-SHA256, a 1080 atinge 1180 kH/s, enquanto a 1080 Ti atinge 1640 kH/s. Em um único geração de placas de vídeo, a taxa de hash de ataque aumentou quase 40%. Pense nisso.
Primeiro, um pequeno teste hello world para ver se as coisas estão funcionando. Fiz o download do hashcat. Fiz login em nossa demonstração em try.discourse.org e criei uma nova conta com a senha 0234567890
Verifiquei o banco de dados e isso gerou os seguintes valores nas colunas hash e salt do banco de dados para esse novo usuário:
hash
93LlpbKZKficWfV9jjQNOSp39MT0pDPtYx7/gBLl5jw=
salZWVhZWQ4YjZmODU4Mzc0M2E2ZDRlNjBkNjY3YzE2ODA=
O Hashcat requer o seguinte formato de arquivo de entrada: uma linha por hash, com o tipo de hash, o número de iterações, o sal e o hash (codificado em base64) separados por dois pontos:
type iter salt hash
sha256:64000:ZWVhZWQ4YjZmODU4Mzc0M2E2ZDRlNjBkNjY3YzE2ODA=:93LlpbKZKficWfV9jjQNOSp39MT0pDPtYx7/gBLl5jw=
Vamos fazer o hashcat e ver se funciona:
./h64 -a 3 -m 10900 .\one-hash.txt 0234567?d?d?d
Observe que essa é uma quantidade de trabalho intencionalmente pequena, pois o senhor está tentando adivinhar apenas três dígitos. E, com certeza, conseguimos decifrá-la rapidamente! O senhor está vendo a senha no final? Conseguimos.
sha256:64000:ZWVhZWQ4YjZmODU4Mzc0M2E2ZDRlNjBkNjY3YzE2ODA=:93LlpbKZKficWfV9jjQNOSp39MT0pDPtYx7/gBLl5jw=:0234567890
Agora que sabemos que funciona, vamos ao que interessa. Mas vamos começar com calma. Quanto tempo leva para um ataque de força bruta a senha mais fácil possível do Discourse, 8 números – que são “apenas” 108 combinações, um pouco mais de cem milhões.
Hash.Type........: PBKDF2-HMAC-SHA256
Time.Estimated...: Fri Jun 02 00:15:37 2017 (1 hour, 0 mins)
Guess.Mask.......: ?d?d?d?d?d?d?d?d [8]
Mesmo com uma GPU top de linha, isso é … OK, eu acho. Lembre-se de que estamos testando apenas um hash, portanto, o senhor precisaria de uma hora por linha (usuário) na tabela. E tenho mais más notícias para o senhor: O Discourse não permitiu senhas de 8 caracteres para já há algum tempo. Quanto tempo leva se tentarmos senhas numéricas mais longas?
?d?d?d?d?d?d?d?d?d [9]
Fri Jun 02 10:34:42 2017 (11 hours, 18 mins)
?d?d?d?d?d?d?d?d?d?d [10]
Tue Jun 06 17:25:19 2017 (4 days, 18 hours)
?d?d?d?d?d?d?d?d?d?d?d [11]
Mon Jul 17 23:26:06 2017 (46 days, 0 hours)
?d?d?d?d?d?d?d?d?d?d?d?d [12]
Tue Jul 31 23:58:30 2018 (1 year, 60 days)
Mas as senhas com todos os dígitos são fáceis para bebês! Que tal um pouco de reais senhas que usam pelo menos letras minúsculas, ou letras minúsculas + maiúsculas + dígitos?
Guess.Mask.......: ?l?l?l?l?l?l?l?l [8]
Time.Estimated...: Mon Sep 04 10:06:00 2017 (94 days, 10 hours)
Guess.Mask.......: ?1?1?1?1?1?1?1?1 [8] (-1 = ?l?u?d)
Time.Estimated...: Sun Aug 02 09:29:48 2020 (3 years, 61 days)
Um ataque de força bruta para tentar cada letra e número não está parecendo muito bom para nós neste momento, mesmo com uma GPU de ponta. Mas e se dividirmos o número por oito … colocando oito placas de vídeo em uma única máquina? Isso está bem ao alcance do orçamento de uma pequena empresa ou de um indivíduo rico. Infelizmente, dividir 38 meses por 8 não é uma redução tão drástica no tempo de ataque. Em vez disso, vamos falar sobre ataques de estados-nação em que eles têm o orçamento para lançar milhares dessas GPUs no problema (1,1 dia), talvez até mesmo dezenas de milhares (2,7 horas), então … sim. Mesmo considerando um mínimo de 10 caracteres para a senha, o senhor está com sérios problemas nesse ponto.
Se quisermos que o Discourse seja resistente a ataques de estados-nação, é claro que precisaremos fazer melhor. O Hashcat tem um modo prático de benchmark, e o aqui está uma lista ordenada dos hashes mais fortes (mais lentos) que o Hashcat conhece comparada em um equipamento com 8 GPUs Nvidia GTX 1080. Das coisas que reconheço nessa lista, bcrypt, scrypt e PBKDF2-HMAC-SHA512 se destacam.
Meus resultados rápidos do hashcat me deram a certeza de que não estávamos fazendo nada de muito errado com os hashes de senha do Discourse armazenados no banco de dados. Mas eu queria ter certeza completamente seguroPor isso, contratei alguém com experiência em segurança e testes de penetração para, sob um NDA assinado, tentar decifrar os hashes de senha de dois sites do Discourse ativos e muito populares que atualmente hospedamos.
Recebi dois conjuntos de hashes de senha de duas comunidades diferentes do Discourse, contendo 5.909 e 6.088 hashes, respectivamente. Ambos usaram o algoritmo PBKDF2-HMAC-SHA256 com um fator de trabalho de 64k. Usando o hashcat, minha GPU Nvidia GTX 1080 Ti gerou esses hashes a uma taxa de aproximadamente 27.000/s.
Em comum a todas as comunidades de discurso estão os vários requisitos de senha:
- Todos os usuários devem ter uma senha com comprimento mínimo de 10 caracteres.
- Todos os administradores devem ter uma senha com comprimento mínimo de 15 caracteres.
- Os usuários não podem usar nenhuma senha que corresponda a uma lista negra das 10.000 senhas mais usadas.
- Os usuários podem optar por criar um nome de usuário e uma senha ou usar vários mecanismos de autenticação de terceiros (Google, Facebook, Twitter, etc.). Se essa opção for selecionada, uma senha segura e aleatória de 32 caracteres será gerada automaticamente. Não é possível saber se uma determinada senha foi digitada por humanos ou gerada automaticamente.
Usando listas e máscaras de senhas comuns, decifrei 39 dos 11.997 hashes em cerca de três semanas, 25 da comunidade ████████ e 14 da comunidade ████████.
Esse é um pesquisador de segurança que geralmente realiza esse tipo de auditoria, portanto, todos os ataques usados listas de palavrasjuntamente com padrões eficazes conhecidos e máscaras derivadas da experiência anterior do pesquisador com quebra de senhas, em vez de força bruta. Isso recuperou as seguintes senhas (e uma duplicada):
007007bond 123password 1qaz2wsx3e A3eilm2s2y Alexander12 alexander18 belladonna2 Charlie123 Chocolate1 christopher8 Elizabeth1 Enterprise01 Freedom123 greengrass123 hellothere01 I123456789 Iamawesome khristopher l1ghthouse |
l3tm3innow Neversaynever password1235 pittsburgh1 Playstation2 Playstation3 Qwerty1234 Qwertyuiop1 qwertyuiop1234567890 Spartan117 springfield0 Starcraft2 strawberry1 Summertime Testing123 testing1234 thecakeisalie02 Thirteen13 Welcome123 |
Se multiplicarmos esse esforço por 8 e dobrarmos o tempo permitido, é possível que um muito atacante motivado, ou um com um conjunto sofisticado de listas de palavras e máscaras, poderia eventualmente recuperar 39 × 16 = 624 senhas, ou cerca de cinco por cento do total de usuários. Isso é razoável, mas maior do que eu gostaria. Planejamos adicionar uma tabela do tipo hash em versões futuras do Discourse, para que possamos mudar para um sistema ainda mais seguro (leia-se: muito mais lento), o esquema de hashing de senha no próximo ano ou dois.
bcrypt $2*$, Blowfish (Unix)
20273 H/s
scrypt
886.5 kH/s
PBKDF2-HMAC-SHA512
542.6 kH/s
PBKDF2-HMAC-SHA256
1646.7 kH/s
Depois desse exercício, agora tenho uma compreensão muito mais profunda do nosso pior cenário de segurança, um comprometimento do banco de dados combinado com um ataque profissional de hashing de senha off-line. Também posso recomendar com mais confiança e apoiar nosso trabalho de engenharia para tornar o Discourse seguro para todos. Portanto, se, como eu, o senhor não tem certeza absoluta de que está fazendo as coisas com segurança, é hora de colocar essas suposições à prova. Não fique esperando que os hackers o ataquem – o senhor não está seguro. hacker, hackeie a si mesmo!
[advertisement] No Stack Overflow, colocamos os desenvolvedores em primeiro lugar. Já o ajudamos a encontrar respostas para suas perguntas difíceis sobre codificação; agora, deixe-nos ajudá-lo encontre seu próximo emprego. |