
A vulnerabilidade Heartbleed `CVE-2014-0160` é uma falha grave de implementação na biblioteca OpenSSL, que permite que atacantes roubem dados da memória do servidor vítima. O conteúdo dos dados roubados depende do que está presente na memória do servidor. Ela pode potencialmente conter chaves privadas, chaves de sessão TLS, nomes de usuário, senhas, cartões de crédito, etc. A vulnerabilidade está na implementação do protocolo Heartbeat, que é usado pelo SSL/TLS para manter a conexão ativa.
O bug Heartbleed CVE-2014-0160 é uma grave falha de implementação na biblioteca OpenSSL, que permite que atacantes roubem dados da memória do servidor vítima. O conteúdo dos dados roubados depende do que está presente na memória do servidor. Ele pode potencialmente conter chaves privadas, chaves de sessão TLS, nomes de usuário, senhas, cartões de crédito, etc. A vulnerabilidade está na implementação do protocolo Heartbeat, que é usado pelo SSL/TLS para manter a conexão ativa.
O intervalo de versões afetadas do OpenSSL vai de 1.0.1 a 1.0.1f. A versão na VM Ubuntu é 1.0.1.
O ataque Heartbleed é baseado na solicitação Heartbeat. Essa solicitação apenas envia alguns dados ao servidor, e o servidor copia os dados para seu pacote de resposta, de modo que todos os dados são ecoados de volta. No caso normal, suponha que a solicitação inclua 3 bytes de dados ”ABC”, então o campo de comprimento tem o valor 3. O servidor colocará os dados na memória e copiará 3 bytes do início dos dados para seu pacote de resposta. No cenário de ataque, a solicitação pode conter 3 bytes de dados, mas o campo de comprimento pode dizer 1003. Quando o servidor constrói seu pacote de resposta, ele copia a partir do início dos dados (ou seja, “ABC”), mas copia 1003 bytes, em vez de 3 bytes. Esses 1000 bytes extras obviamente não vêm do pacote de solicitação; eles vêm da memória privada do servidor e podem conter informações de outros usuários, chaves secretas, senhas, etc.
Agora, altere o campo de comprimento da solicitação. Primeiro, vamos entender como o pacote de resposta Heartbeat é construído a partir da figura acima. Quando o pacote de solicitação Heartbeat chega, o servidor analisa o pacote para obter o payload e o valor Payload_length (que está destacado acima). Aqui, o payload é apenas uma string de 3 bytes "ABC" e o valor Payload_length é exatamente 3. O programa do servidor pegará cegamente esse valor de comprimento do pacote de solicitação. Em seguida, ele constrói o pacote de resposta apontando para a memória que armazena "ABC" e copia Payload_length bytes para o payload da resposta. Dessa forma, o pacote de resposta conteria uma string de 3 bytes "ABC".
Em seguida, lance o ataque Heartbleed como mostrado na figura abaixo. Mantenha o mesmo payload (3 bytes), mas defina o campo Payload_length para 1003. O servidor novamente pegará cegamente esse valor Payload_length ao construir o pacote de resposta. Desta vez, o programa do servidor apontará para a string "ABC" e copiará 1003 bytes da memória para o pacote de resposta como payload. Além da string ”ABC”, os 1000 bytes extras são copiados para o pacote de resposta, que pode ser qualquer coisa da memória, como atividade secreta, informações de registro, senhas e assim por diante.
O código do ataque permite que o valor Payload_length mude. Por padrão, o valor é definido como um valor bastante grande (0x4000), mas pode ser reduzido.
A maneira mais fácil de corrigir a vulnerabilidade Heartbleed é atualizar a biblioteca OpenSSL para a versão mais recente. No entanto, o objetivo é corrigir a vulnerabilidade por meio do código-fonte.
Formato do pacote de solicitação/resposta Heartbeat
struct {
HeartbeatMessageType type; // 1 byte: request or the response
uint16 payload_length; // 2 byte: the length of the payload
opaque payload[HeartbeatMessage.payload_length];
opaque padding[padding_length];
} HeartbeatMessage;
O primeiro campo (1 byte) do pacote é a informação de tipo, e o segundo campo (2 bytes) é o comprimento do payload, seguido pelo payload real e pelo preenchimento. O tamanho do payload deve ser o mesmo que o valor no campo de comprimento do payload, mas no cenário de ataque, o comprimento do payload pode ser definido para um valor diferente. O trecho de código a seguir mostra como o servidor copia os dados do pacote de solicitação para o pacote de resposta.
Processar o pacote de solicitação Heartbeat e gerar o pacote de resposta
/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
// Read from type field first
hbtype = *p++; /* After this instruction, the pointer
* p will point to the payload_length field */
// Read from the payload_length field from the request packet
n2s(p, payload); /* Function n2s(p, payload) reads 16 bits
* from pointer p and store the value
* in the INT variable "payload". */
pl = p; // pl points to the beginning of the payload content
if (hbtype == TLS1_HB_REQUEST)
{
unsigned char *buffer, *bp;
int r;
/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
// Enter response type, length and copy payload *bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
// copy payload
memcpy(bp, pl, payload); /* pl is the pointer which
* points to the beginning
* of the payload content */
bp += payload;
// Random padding
RAND_pseudo_bytes(bp, padding);
// this function will copy the 3+payload+padding bytes
// from the buffer and put them into the heartbeat response
// packet to send back to the request client side.
OPENSSL_free(buffer);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
}
A vulnerabilidade está aqui
// copy payload
memcpy(bp, pl, payload);
Não há verificação para determinar se pl é válido ou não. Portanto, uma violação de memória pode ocorrer.
Correções:
memcpy()As correções foram feitas na VM, mas não são mostradas neste repositório.
Obrigado pelo seu interesse, este projeto foi divertido e esclarecedor!