"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".
Hoje
ao ler as matérias sobre o Heartbleed, a notícias mais “punk” da semana, pois
apontou uma grave falha de segurança no OpenSSL, me bateu uma saudade das aulas
de lógica de programação, C, algoritmos enfim de todas as loucuras que aprendi
no curso de Ciência da Computação. Aliás, abre parêntese - só louco faz um
curso desses e aguenta chegar até o final e se formar – fecha parêntese.
Transcrevo
resumo do texto que li no MSN, por considerar o mais didático e ao mesmo tempo
técnico.
Então
vamos lá, Heartbleed, é falha de segurança que pode expor inúmeras transações
criptografadas para qualquer hacker que souber usá-la. OK, mas como isto
realmente funciona? Na verdade, é muito simples – e por isso tão alarmante.
Em
termos gerais, o Heartbleed é uma falha no OpenSSL, 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 como 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 simples.
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 Heartbleed (algo como “hemorragia cardíaca”).
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, 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.
De
acordo com Sean Cassidy, o problema real, que gerou uma crise de segurança,
está nesta pequena linha de código:
memcpy(bp, pl, payload);
Explicando,
memcpy é um comando que copia dados,
e requer três informações (parâmetros) para fazer o trabalho – são os termos
dos parênteses descritos abaixo:
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 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 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 também. Graças a Deus! Ainda bem que
o mundo binário é assim SIMPLES e 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. Conta Sean Cassidy.
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.
Comentários