SSL/TLS : Faille Heartbleed

12
Failles SSL/TLS Heartbleed

Transcript of SSL/TLS : Faille Heartbleed

Page 1: SSL/TLS : Faille Heartbleed

Failles SSL/TLSHeartbleed

Page 2: SSL/TLS : Faille Heartbleed

Thomas Moegli

๏ L’extension Heartbeat du protocole TLS/DTLS est utilisé pour vérifier si une connexion entre deux équipements est encore en vie

๏ Fonctionne au dessus de la couche TLS Record ๏ Maintient la connexion en échangeant régulièrement un heartbeat

๏ Introduit en 2012 par la RFC 6520 ๏ Implémenté dans OpenSSL en décembre 2011

๏ Une erreur dans l’implémentation a conduit à cette vulnérabilité ๏ Cette erreur est présente dans les version 1.0.1 à 1.01f d’OpenSSL ๏ Il s’agit d’un développeur allemand, Robin Seggelmann, qui a introduit cette

vulnérabilité dans le code d’OpenSSL en décembre 2011, version qui a été diffusée à partir de mars 2012

๏ Erreur découverte en décembre 2013, à quelques jours d’intervalle, par deux équipes : l’une de Google, l’autre de Condominium (une société finlandaise)

๏ Découverte tenue secrète jusqu’au mardi 8 avril afin de laisser le temps de développer des correctifs et ne pas avertir des utilisateurs malintentionnés

Faille Heartbleed Extension SSL Heartbeat

51

Page 3: SSL/TLS : Faille Heartbleed

Thomas Moegli

Faille Heartbleed Extension SSL Heartbeat

52

Page 4: SSL/TLS : Faille Heartbleed

Thomas Moegli

Fonctionnement

๏ Echange de deux types de messages : HeartbeatRequest et Heartbeat Response ๏ Lors de l’utilisation de TLS

๏ L’un des clients envoie un message HeartbeatRequest à son destinataire. ๏ Le destinataire reçoit le message et renvoie un HeartbeatResponse. Cela permet ainsi de maintenir la connexion ๏ Si aucune réponse n’est reçue, la connexion est terminée

๏ Lors de l’utilisation de DTLS ๏ L’un des clients envoie un message HeartbeatRequest à son destinataire ๏ Le destinataire doit répondre immédiatement par un message HeartbeatResponse ๏ Si aucune réponse n’est reçue dans un délai défini, le client renvoie un message HeartbeatRequest ๏ Le nombre de renvoi est défini, si toujours aucune réponse n’est parvenu, la connexion DTLS est terminée

๏ Lorsque le destinataire reçoit le message HeartbeatRequest, il doit renvoie une copie identique du message dans la réponse HeartbeatResponse

๏ L’émetteur vérifie que la réponse reçue correspond à son message d’origine. ๏ Si le message est identique, la connexion est maintenue ๏ Si le message est différent, le message HeartbeatRequest est renvoyé. Le nombre de renvoi est déterminé.

Faille Heartbleed Extension SSL Heartbeat : Fonctionnement

53

Page 5: SSL/TLS : Faille Heartbleed

Thomas Moegli

Requête HeartBeat

๏ Implémentation OpenSSL pour la requête HeartBeat ๏ Se situe dans openssl-1.0.1/ssl/d1_both.c

๏ Fonction dtls1_heartbeat ➔

๏ L’extrait ci-dessus montre que la taille maximale d’une requête Heartbeat est de 16Ko (=16384 octets)

๏ Cette taille (Payload + Padding) inclut : ๏ 1 octet pour identifier que le message est de type TLS

Heartbeat Request ๏ 2 octets utilisés pour indiquer la longueur du message

Faille Heartbleed Extension SSL Heartbeat : Implémentation OpenSSL

54

int dtls1_heartbeat(SSL *s) { unsigned char *buf, *p; int ret; unsigned int payload = 18; /* Sequence number + random bytes */ unsigned int padding = 16; /* Use minimum padding */ /* Only send if peer supports and accepts HB requests... */ if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) || s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS) { SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT); return -1; } /* ...and there is none in flight yet... */ if (s->tlsext_hb_pending) { SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PENDING); return -1; } /* ...and no handshake in progress. */ if (SSL_in_init(s) || s->in_handshake) { SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_UNEXPECTED_MESSAGE); return -1; } /* Check if padding is too long, payload and padding * must not exceed 2^14 - 3 = 16381 bytes in total. */ OPENSSL_assert(payload + padding <= 16381); /* Create HeartBeat message, we just use a sequence number * as payload to distuingish different messages and add * some random stuff. * - Message Type, 1 byte * - Payload Length, 2 bytes (unsigned int) * - Payload, the sequence number (2 bytes uint) * - Payload, random bytes (16 bytes uint) * - Padding */ buf = OPENSSL_malloc(1 + 2 + payload + padding); p = buf; /* Message Type */ *p++ = TLS1_HB_REQUEST; /* Payload length (18 bytes here) */ s2n(payload, p); /* Sequence number */ s2n(s->tlsext_hb_seq, p); /* 16 random bytes */ RAND_pseudo_bytes(p, 16); p += 16; /* Random padding */ RAND_pseudo_bytes(p, padding); ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding); if (ret >= 0) { if (s->msg_callback) s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding, s, s->msg_callback_arg); dtls1_start_timer(s); s->tlsext_hb_pending = 1; } OPENSSL_free(buf); return ret; }

/* Check if padding is too long, payload and padding * must not exceed 2^14 - 3 = 16381 bytes in total. */ OPENSSL_assert(payload + padding <= 16381);

Page 6: SSL/TLS : Faille Heartbleed

Thomas Moegli

Réponse Heartbeat ๏ Le client répond par un message HeartBeat Response contenant une

copie des données Payload provenant de la requête Heartbeat ๏ Implémentation OpenSSL pour la réponse HeartBeat

๏ Se situe dans openssl-1.0.1/ssl/t1_libc

๏ Fonction tls1_process_heartbeat

Faille Heartbleed Extension SSL Heartbeat : Implémentation OpenSSL

55

int tls1_process_heartbeat(SSL *s) { unsigned char *p = &s->s3->rrec.data[0], *pl; unsigned short hbtype; unsigned int payload; unsigned int padding = 16; /* Use minimum padding */ /* Read type and payload length first */ hbtype = *p++; n2s(p, payload); pl = p; if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, &s->s3->rrec.data[0], s->s3->rrec.length, s, s->msg_callback_arg); if (hbtype == TLS1_HB_REQUEST) { unsigned char *buffer, *bp; int r; /* Allocate memory for the response, size is 1 bytes * 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); memcpy(bp, pl, payload); bp += payload; /* Random padding */ RAND_pseudo_bytes(bp, padding); r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); if (r >= 0 && s->msg_callback) s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding, s, s->msg_callback_arg); OPENSSL_free(buffer); if (r < 0) return r; } else if (hbtype == TLS1_HB_RESPONSE) { unsigned int seq; /* We only send sequence numbers (2 bytes unsigned int), * and 16 random bytes, so we just try to read the * sequence number */ n2s(pl, seq); if (payload == 18 && seq == s->tlsext_hb_seq) { } return 0; } s->tlsext_hb_seq++; s->tlsext_hb_pending = 0; }

Page 7: SSL/TLS : Faille Heartbleed

Thomas Moegli

Réponse Heartbeat ๏ L’extrait ci-dessus montre l’implémentation de la réponse Heartbeat

๏ En premier, il détermine si le type de message reçu est un TLS Heartbeat Request. Il extrait la longueur du Payload

๏ Il alloue ensuite de la mémoire pour la réponse Heartbeat ๏ 1 octet pour indiquer le type de message (TLS Heartbeat Response) ๏ 2 octets pour indiquer la longueur du Payload

๏ Il copie le Payload du message HeartbeatRequest dans la réponse HeartbeatResponse et renvoie cela à l’émetteur

Faille Heartbleed Extension SSL Heartbeat : Implémentation OpenSSL

56

int tls1_process_heartbeat(SSL *s) { unsigned char *p = &s->s3->rrec.data[0], *pl; unsigned short hbtype; unsigned int payload; unsigned int padding = 16; /* Use minimum padding */ /* Read type and payload length first */ hbtype = *p++; n2s(p, payload); pl = p; if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, &s->s3->rrec.data[0], s->s3->rrec.length, s, s->msg_callback_arg); if (hbtype == TLS1_HB_REQUEST) { unsigned char *buffer, *bp; int r; /* Allocate memory for the response, size is 1 bytes * 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); memcpy(bp, pl, payload); bp += payload; /* Random padding */ RAND_pseudo_bytes(bp, padding); r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); if (r >= 0 && s->msg_callback) s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding, s, s->msg_callback_arg); OPENSSL_free(buffer); if (r < 0) return r; } else if (hbtype == TLS1_HB_RESPONSE) { unsigned int seq; /* We only send sequence numbers (2 bytes unsigned int), * and 16 random bytes, so we just try to read the * sequence number */ n2s(pl, seq); if (payload == 18 && seq == s->tlsext_hb_seq) { } return 0; } s->tlsext_hb_seq++; s->tlsext_hb_pending = 0; }

/* Allocate memory for the response, size is 1 bytes * 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); memcpy(bp, pl, payload); bp += payload; /* Random padding */ RAND_pseudo_bytes(bp, padding); r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);

Page 8: SSL/TLS : Faille Heartbleed

Thomas Moegli

๏ L’implémentation de la réponse Heartbeat contient un bug important ๏ Dans l’implémentation précédente, la réponse Heartbeat copie le Payload reçu sans vérifier si la longueur effective du

Payload présent dans la requête correspond à la valeur indiquée dans le champ Length de cette même requête. ๏ L’erreur se situe sur cette ligne :

๏ Si le champ Length contient une valeur définie qui est plus grand que la longueur effective du Payload, l’opération memcpy va copier le Payload de la requête Heartbeat ainsi qu’une partie des informations situées dans la mémoire du récepteur (les informations situées après le Payload)

๏ La valeur Length d’une requête Heartbeat peut être définie jusqu’à une valeur maximale de 65’535 octets ๏ Ce bug permet donc de récupérer, via une requête trafiquée, jusqu’à 65’535 octets de la mémoire interne d’un serveur alors que

ces informations sont normalement chiffrés et ne transitent que via le tunnel sécurisée ๏ Parmi ces informations peuvent figurer des comptes utilisateurs, des mots de passes, des clés de session, etc…

Faille Heartbleed Extension SSL Heartbeat : Bug d’implémentation

57

… memcpy(bp, pl, payload); …

Page 9: SSL/TLS : Faille Heartbleed

Thomas Moegli

๏ Le correctif apporte deux tâches supplémentaires : ๏ En premier, il vérifie si la longueur effective du Payload de la requête est égale à 0 ou non

๏ Si la longueur vaut 0, le message est silencieusement supprimé ๏ En second, il vérifie si la longueur effective du Payload correspond à la valeur indiquée dans le message

๏ Si la longueur effective est inférieur, le message est silencieusement supprimé

Faille Heartbleed Extension SSL Heartbeat : Correctif

58

… /* Read type and payload length first */ hbtype = *p++; n2s(p, payload); pl = p; if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, &s->s3->rrec.data[0], s->s3->rrec.length, s, s->msg_callback_arg); …

if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, &s->s3->rrec.data[0], s->s3->rrec.length, s, s->msg_callback_arg); /* Read type and payload length first */ if (1 + 2 + 16 > s->s3->rrec.length) return 0; /* silently discard */ hbtype = *p++; n2s(p, payload); if (1 + 2 + payload + 16 > s->s3->rrec.length) return 0; /* silently discard per RFC 6520 sec. 4 */ pl = p;

\openssl-1.0.1\ssl\t1_lib.c \openssl-1.0.1\ssl\t1_lib.c

Page 10: SSL/TLS : Faille Heartbleed

Thomas Moegli

๏ Référencement du bug sous le nom « CVE-2014-0160 » ๏ La note officielle sur ce bug a été publiée par le OpenSSL

Group sur :https://www.openssl.org/news/secadv_20140407.txt

Faille Heartbleed Extension SSL Heartbeat : Note officielle

59

OpenSSL Security Advisory [07 Apr 2014]========================================

TLS heartbeat read overruns (CVE-2014-0160) ==========================================

A missing bounds check in the handling of the TLS heartbeat extension can be used to reveal up to 64k of memory to a connected client or server. Only 1.0.1 and 1.0.2-beta releases of OpenSSL are affected including 1.0.1f and 1.0.2-beta1.

Thanks for Neel Mehta of Google Security for discovering this bug and to Adam Langley <[email protected]> and Bodo Moeller <[email protected]> for preparing the fix.

Affected users should upgrade to OpenSSL 1.0.1g. Users unable to immediately upgrade can alternatively recompile OpenSSL with -DOPENSSL_NO_HEARTBEATS.

1.0.2 will be fixed in 1.0.2-beta2.

Page 11: SSL/TLS : Faille Heartbleed

Thomas Moegli

๏ Il est difficile de savoir si cette vulnérabilité a été exploitée car les attaques ne laissent théoriquement pas de traces ๏ Cette vulnérabilité ne permet pas de viser un utilisateur en particulier mais permet de récupérer une quantité

importante de fichiers logs, d’identifiants de connexion et des cookies ๏ Fragilisée par le scandale du programme de surveillance Prism, les sites Internet concernés par la faille ont très vite

réagi et ont effectué la mise à jour de leur libraire OpenSSL au début de la semaine (notamment Yahoo) ๏ Ils ont également averti leurs utilisateurs de changer leur mot de passe

๏ La plupart des grandes entreprises n’ont pas été concernés par la faille grâce à leurs choix conservateurs en terme de sécurisation des échanges sur Internet

๏ Ils ne recourent pas à OpenSSL ou n’en déploient pas de versions récentes ๏ Apple, Microsoft, Amazon ou eBay ont déclarés qu’ils n’étaient pas concernés par la faille ๏ Ce ne fut pas le cas de Yahoo et de plusieurs sociétés bancaires (bien que pour la plupart, la mise en place de procédures

d’authentification double permet de limiter l’exploitation de la faille)

Faille Heartbleed Extension SSL Heartbeat : Impacts

60

Page 12: SSL/TLS : Faille Heartbleed

Thomas Moegli

๏ Périphériques affectés ๏ Téléphones Android tournant sur la version 4.1.1 (Jelly Bean) ๏ Routeurs Cisco ๏ Routeurs Juniper ๏ Famille de produits Western Digital My Cloud

๏ Systèmes d’exploitation affectés ๏ Debian Wheezy, OpenSSL 1.0.1e-2+deb7u4 ๏ Ubuntu 12.04.4 LTS, OpenSSL 1.0.1-4ubuntu5.11 ๏ CentOS 6.5, OpenSSL 1.0.1e-15 ๏ Fedora 18, OpenSSL 1.0.1e-4 ๏ OpenBSD 5.3 (OpenSSL 1.0.1c 10 May 2012) and 5.4 (OpenSSL 1.0.1c 10 May 2012) ๏ FreeBSD 10.0 - OpenSSL 1.0.1e 11 Feb 2013 ๏ NetBSD 5.0.2 (OpenSSL 1.0.1e) ๏ OpenSUSE 12.2 (OpenSSL 1.0.1c)

Faille Heartbleed Extension SSL Heartbeat : Systèmes touchés

61