Como funciona o Heartbleed: o código por trás da assustadora falha de segurança na internet
Erro no código do OpenSSL está ativo desde 2011 e anda preocupando especialistas em segurança na rede. Você certamente já ouviu falar sobre o Heartbleed, a falha de segurança que pode expor inúmeras transações criptografadas para qualquer hacker que souber usá-la. Mas como isto realmente funciona? Na verdade, é muito simples – e por isso tão aterrorizante.
Em termos gerais, o Heartbleed é uma falha no OpenSSL, um software que permite ao seu computador e a um servidor saberem que são quem dizem que são. Ele deixou grandes sites – como Yahoo, Flickr e Imgur – vulneráveis a roubo de dados por anos, desde 2011. É algo bem assustador, e merece um olhar mais atento.
A beleza de um projeto de código aberto como o OpenSSL é que qualquer um pode olhar o código; não há como esconder algo de propósito. Na verdade, você pode ver exatamente onde o Heartbleed nasceu e onde foi consertado, mesmo que não entenda muito de código.
Por isso, é tão surpreendente que o Heartbleed passou despercebido por tanto tempo. Dois anos se escondendo à vista de todos, sem ser notado até mesmo por programadores experientes. Mas, uma vez que você chega à parte que deu errado, o problema se torna extremamente claro, e terrivelmente simples.
Ouça a batida do meu coração
O Heartbleed não é um problema com as tecnologias TLS/SSL que criptografam a internet. Não é nem mesmo um problema com a forma como o OpenSSL funciona na teoria. É apenas um erro no código.
Quando dois servidores se preparam para fazer um aperto de mão criptografado, eles realizam algo chamado de “heartbeat” (batimento cardíaco) – é nisso que se inspira o nome do bug.
Heartbeats são uma forma de dois computadores que conversam entre si garantirem que o outro ainda está vivo: dessa forma, se algo der errado durante o processo, ele não continua. Eles fazem isso enviando dados um para o outro, de forma constante.
O cliente (você!) envia o seu heartbeat para o servidor (seu banco, por exemplo), e o servidor o entrega de volta. Dessa forma, se algo der errado durante a transação – por exemplo, se um computador parar de funcionar – o outro vai saber, porque os batimentos cardíacos saem de sincronia.
É um processo simples, repetido milhões de vezes por dia em todo o mundo. Mas de alguma forma, versões bugadas do OpenSSL conseguiram estragar tudo. Sean Cassidy explica tudo em bastante profundidade no seu blog.
A mentira
O problema real, que gerou uma crise de segurança, está nesta pequena linha de código:
memcpy(bp, pl, payload);
O texto vai ficar um pouco técnico, mas calma – tentaremos deixar tudo bem claro. Simplificando, memcpy é um comando que copia dados, e requer três informações para fazer o trabalho – são os termos dos parênteses.
• pl: onde estão os dados que serão enviados no heartbeat;
• bp: o destino final dos dados no heartbeat;
• payload: o tamanho desses dados. Basicamente, o heartbeat envia alguns dados para o servidor – seu banco, por exemplo – e ele precisa devolver para você exatamente os mesmos dados. Assim, garante-se que a conexão está segura.
No entanto, a cópia de dados é mais complicada do que parece. Quando o heartbeat vai para o servidor de destino – seu banco, por exemplo – ele não ocupa um espaço realmente vazio de memória. Sempre há alguma coisa gravada, que o computador precisa apagar para então gravar o heartbeat.
Aí está o problema: o comando memcpy pode mentir o tamanho do heartbeat. Ele pode dizer que o arquivo tem 64KB, quando ele na verdade tem 0KB. Então o servidor, confuso, vai alocar 64KB de memória – onde pode haver dados confidenciais – e enviá-los de volta para você.
É assim que hackers conseguem comprometer a segurança de sites usando o Heartbleed. Diga que vai enviar um heartbeat de 64KB, envie na verdade um arquivo de 0KB, e o servidor devolve 64KB de dados – que podem conter senhas ou endereços de e-mail, por exemplo. Repita isso diversas vezes, e você pode conseguir até chaves de criptografia.
Em termos mais técnicos: a função memcpy vai criar um espaço de 64KB (payload) no destino (bp), mas como ele recebe zero dados, esse espaço mantém tudo o que havia nele antes. Quando ele enviar os dados de volta, vai incluir tudo o que há nesse espaço. Com o Heartbleed, é possível pedir informações várias vezes a um servidor, até que ele envie de volta algo bem revelador.
O erro minúsculo recebe uma pequena correção - A correção é tão simples quanto o erro em si:
* Ler primeiro o tipo e tamanho do payload */
if (1 + 2 + 16 > s->s3->rrec.length)
return 0;
/* descartar silenciosamente */
hbtype = *p++;
n2s(p, payload);
if (1 + 2 + payload + 16 > s->s3->rrec.length)
return 0;
/* descartar silenciosamente segundo RFC 6520 seção 4 */
pl = p;
Como explica Sean Cassidy, este código tem duas funções muito simples. A primeira é checar se o heartbeat tem comprimento zero. A segunda garante que a função memcpy não está mentindo o tamanho do payload. E pronto.
Este tipo de erro é comum, e tem um nome: transbordamento de dados, ou estouro de buffer (buffer overflow). Ao escrever código, um dos erros mais comuns é “esquecer de fazer algo óbvio e verificar se os dados inseridos pelo usuário nunca estão errados”. Ainda me lembro do meu professor de C++ no ensino médio, insistindo que a gente verificasse o comprimento dos dados inseridos pelo usuário. Sempre. Só por precaução.
Felizmente, esse bug do OpenSSL é simples, e a correção é fácil de implementar, mesmo que não conserte o dano já feito. No fim, tudo se resume a esse princípio horrível e maravilhoso da computação: o computador sempre vai fazer exatamente o que você diz – nada a menos, e nada a mais. Ele é obediente, mas nem sempre é esperto – então você (ou o programador) precisa ser.
Nenhum comentário
Postar um comentário