Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

RFC 7507: TLS Fallback Signaling Cipher Suite Value (SCSV) for Preventing Protocol Downgrade Attacks

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : B. Moeller, A. Langley (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 25 avril 2015


Le protocole TLS offre un grand nombre de choix : choix de la version, choix des algorithmes cryptographiques, plein d'options... Tous ces choix ne sont pas équivalents en terme de sécurité : les versions anciennes de TLS ont des vulnérabilités absentes des plus récentes, par exemple. Dès qu'un protocole cryptographique a des choix, il y a un risque de sécurité : que l'attaquant tente de perturber la négociation initiale entre les deux parties, pour les amener à choisir les variantes les moins sécurisées, en faisant croire à chacun que son partenaire ne peut pas gérer les meilleures variantes. C'est ce qu'on nomme une attaque par repli (downgrade attack) et c'est une plaie classique des protocoles cryptographiques (sauf de ceux qui n'offrent aucun choix, mais qui ont d'autres problèmes, notamment l'impossibilité d'évoluer). Ce RFC présentait une technique TLS pour empêcher certaines attaques par repli : annoncer un algorithme cryptographique qui n'est pas un vrai algorithme mais qui signale qu'on a effectué un repli, permettant au partenaire de détecter que quelqu'un a interféré avec la communication. Cette technique se nomme SCSV, pour Signaling Cipher Suite Value. Elle a été abandonnée par le RFC 8996, qui retirait du service les versions de TLS vulnérables.

Normalement, un tel signalement n'est pas nécessaire (c'est très bien expliqué dans cet article sur StackExchange), les règles de négociation de TLS se chargent de tout (RFC 5246, sections 7.3 et 7.4). Mais il y a des serveurs TLS bogués qui réagissent mal avec certaines variantes. Au lieu d'indiquer proprement qu'ils ne gèrent pas ces variantes, ils coupent la communication. Un client TLS qui veut donc maximiser ses chances de se connecter va donc réessayer, en ne proposant pas les choix qui ont pu mener au précédent échec. C'est sympa du point de vue de l'interopérabilité mais cette downgrade dance est dangereuse du point de vue de la sécurité : le serveur, lors de la deuxième tentative, ne sait pas qu'il s'agit d'un repli. Prenons l'exemple d'un attaquant qui a trouvé une faille dans TLS 1.0 mais qui n'existe plus dans TLS 1.2 (celui du RFC 5246). Si Alice et Bob savent tous les deux parler 1.2, c'est cette version qu'ils choisiront, par défaut. Il faut donc les convaincre de se replier en 1.0. Un attaquant actif peut perturber la négotiation TLS (par exemple en ne transmettant pas le ServerHello, donnant au client l'impression que le serveur a ignoré son ClientHello). Certains clients vont alors se dire « zut, demander 1.2 perturbe le serveur, je vais réessayer directement en 1.0 ». Et l'attaquant aura atteint son but. Le serveur, qui sait faire du TLS 1.2, verra une demande en 1.0 et se dire juste « tiens, un vieux client qui ne sait pas faire de 1.2 ». Jusqu'à ce nouveau RFC, la seule protection contre ces attaques était de configurer le serveur pour refuser certains choix vraiment trop mauvais, question sécurité. Cette solution était trop rigide (pour reprendre l'exemple précédent, TLS 1.0 n'est pas catastrophique : il est raisonnable d'autoriser les vieux clients à se connecter en 1.0, mais on veut empêcher que les clients récents ne soient amenés à se limiter à 1.0). Au passage, un exemple d'une telle démarche est discutée dans l'article présentant la configuration TLS de mon blog (la ligne GnuTLSPriorities SECURE:-VERS-SSL3.0:-ARCFOUR-128:-ARCFOUR-40).

L'idéal serait bien sûr qu'il n'y ait pas de serveurs bogués, que la négociation TLS normale suffise, et que les clients n'aient jamais à faire de downgrade dance. Mais, dans le monde cruel où nous vivons, cela n'arrivera pas, les programmeurs ne lisent pas les normes et ne testent pas leur travail. À noter que, même en l'absence d'un attaquant actif, on voit parfois des replis malencontreux : un problème temporaire de réseau peut mener le client TLS à se dire « tiens, pas de réponse, je vais réessayer en TLS 1.0 et sans les extensions, pour voir ».

Donc, pour permettre au serveur de détecter que le client a fait un repli à tort, notre RFC introduit un nouveau pseudo-algorithme de chiffrement, TLS_FALLBACK_SCSV, valeur 0x56,0x00 (désormais dans le registre IANA). Il sera envoyé uniquement par le client, jamais par le serveur. Ce n'est pas un vrai algorithme, juste un signalement par le client qu'une première connexion a échoué et que le client tente un repli (section 4 du RFC). Si le client envoie le pseudo-algorithme TLS_FALLBACK_SCSV dans son ClientHello, et indique un protocole de version inférieure à ce que le serveur peut gérer, le serveur peut alors se rendre compte que le client a effectué un repli à tort (cf. section 3). Il peut alors répondre avec un nouveau message d'erreur, l'alerte TLS inappropriate_fallback (valeur 86). Voici ce que ça donne avec Firefox : inappropriate-fallback.png

Le signalement par le client qu'il s'est replié est un (pseudo-)algorithme de chiffrement, pas une extension TLS, car le but est qu'il ne pose de problème avec aucun serveur, même le plus ancien et le plus bogué. Le mécanisme d'indication des algorithmes de chiffrement date des débuts de SSL et on peut donc certainement compter dessus. Au passage, la technique de notre nouveau RFC est la deuxième utilisation de ce principe du SCSV, après la TLS_EMPTY_RENEGOTIATION_INFO_SCSV de la section 3.3 du RFC 5746.

La section 6 de notre RFC explore les cas où le client a intérêt à envoyer un TLS_FALLBACK_SCSV ou pas. Si le client n'a pas pu se connecter en TLS v1 ou supérieur, et se replie sur SSL v3, alors, le TLS_FALLBACK_SCSV est vraiment nécessaire car SSL v3 a de nombreuses faiblesses (la faille Poodle par exemple). Par contre, quand un client a une toute nouvelle version de TLS (à l'heure de la publication de ce RFC, la version 1.3 est en cours de développement), des difficultés avec les vieux serveurs sont à prévoir et il peut être préférable de ne pas envoyer TLS_FALLBACK_SCSV, et d'accepter le repli.

Des mesures faites en novembre 2014 indiquaient que 14 % des serveurs TLS sur l'Internet géraient déjà ce pseudo-algorithme TLS_FALLBACK_SCSV. Si vous voulez tester vous-même, vous pouvez par exemple vous servir d'OpenSSL en ligne de commande :

% openssl s_client -connect google.com:443 -state -fallback_scsv -tls1_1
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL3 alert read:fatal:unknown
SSL_connect:failed in SSLv3 read server hello A
1077786776:error:1409443E:SSL routines:SSL3_READ_BYTES:tlsv1 alert inappropriate fallback:s3_pkt.c:1260:SSL alert number 86
1077786776:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:598:

Ici, on a tenté de se connecter à Google en envoyant le SCSV (option -fallback_scsv) et en indiquant comme numéro de version TLS 1.1 (alors que Google et OpenSSL savent tous les deux faire du 1.2). Google a donc envoyé l'alarme (le message alert inappropriate fallback). Avec un serveur qui ne gère pas SCSV, on aurait au contraire eu une connexion sans alerte. Si, au lieu du programme openssl, on veut le faire depuis une application qu'on écrit, il y a instructions et code sur le Wiki d'OpenSSL. Notez que le test des SSL Labs regarde aussi SCSV (message « This server supports TLS_FALLBACK_SCSV to prevent protocol downgrade attacks » ou bien aucune indication dans le cas contraire). Vu avec tshark, le test avec openssl montrera :

client -> serveur:

        Handshake Protocol: Client Hello
            Version: TLS 1.1 (0x0302)
                Cipher Suite: Unknown (0x5600) [version trop ancienne
		de Wireshark, qui n'affiche pas le nom de la SCSV]

serveur -> client:

    TLSv1.1 Record Layer: Encrypted Alert                                                                     
        Content Type: Alert (21)                                                                              
        Version: TLS 1.1 (0x0302)                                                                             
        Length: 2                                                                                             
        Alert Message: Encrypted Alert         

(L'alerte est chiffrée et donc pas décodée par défaut par Wireshark.)

Côté navigateurs Web, Firefox et Chrome gèrent cette technique SCSV mais il semble qu'Internet Explorer ne le fera pas.

Et, pour finir, une bonne explication de SCSV, avec des exemples Wireshark. Et merci à Florian Maury pour sa relecture.


Téléchargez le RFC 7507

Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)

Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)