Surveillance généralisée : aux limites de PGP

MISC n° 075 | septembre 2014 | Émilien (gapz) Gaspar
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
De l'hypothétique fin du projet Truecrypt en passant par la voie ouverte à la résolution du problème du logarithme discret : le monde de la cryptographie bouillonne, des projets à destination du grand public naissent un peu partout. Nous allons tenter, au milieu de ce foisonnement d'analyses et d'idées, de reprendre un outil bien connu, PGP, et de le confronter là où l'ensemble des modèles de menaces achoppe : la surveillance généralisée.

1. Introduction

C'était en 1991, Phil Zimmermann finissait d'écrire la première version de PGP. Quelques années plus tard, son format de message était standardisé et c'était au tour de GnuPG de voir le jour. Nous sommes en 2013, plus d'une décennie plus tard, l'ensemble des populations des pays industrialisés est informé par le biais des grands journaux de la surveillance systématique pratiquée par différents organismes de renseignement, en particulier la NSA. Cela va faire un an maintenant. Depuis, toutes les conférences de sécurité nous parlent de vie privée et en appellent à l'utilisation massive de la cryptographie, de PGP. Nous allons dans cet article rappeler dans un premier temps la relation difficile entre un utilisateur classique et la cryptographie pour ensuite détailler des limites importantes de PGP à l'heure où le tout à chacun cherche à se protéger de la surveillance permanente.

2. Cryptographie et grand public

2.1 Bilan unanime

« There are two kinds of cryptography in this world : cryptography that will stop your kid sister from reading your files, and cryptography that will stop major governments from reading your files. »

Ces quelques mots de Bruce Schneier datent de 1996, année où la législation française (qui entourait notamment PGP) commençait à être assouplie pour que les outils de cryptographie s'ouvrent doucement à un usage non militaire. Une des questions que l'on peut lever désormais grâce aux fameuses révélations d'Edward Snowden, est l'absence totale de limite dans ce qui est envisageable en tant que dispositifs déployés à des fins de surveillance. L'expérience nous l'avait déjà pourtant prouvée à plusieurs reprises, tant au niveau de l'élaboration des moyens cryptographiques qu'à leurs implémentations, libres et propriétaires. Pour ne citer que ces exemples : l'intervention de la NSA dans l'élaboration de DES au cours des années 1970 ou plus récemment la potentielle porte dérobée du générateur pseudo-aléatoire Dual_EC_DRBG [1] (qui aboutira à son retrait des recommandations du NIST). On peut également citer l'influence caractérisée de la part d'Intel pour faire reposer le générateur /dev/random de Linux sur la seule instruction RDRAND [2], ou encore la faille d'OpenSSL/heartbleed qui réactive la polémique sur la possibilité qu'un contributeur intègre sciemment une faille de sécurité. On pourrait également lister l'ensemble des portes dérobées volontairement introduites par les grands constructeurs (de Samsung à Apple en passant par Crypto AG), ou même épiloguer sur la probable collaboration de ces derniers avec les différents services de renseignements puissants de ce monde. Après une si dense expérience, le bilan qui peut être fait est un des classiques de la paranoïa du monde de la sécurité : ne faire confiance à personne.

2.2 À qui faire confiance ?

L'idée selon laquelle chaque personne serait mieux protégée si elle développait l'intégralité des moyens dont elle a besoin n'est bien entendu pas valide. Ni même de penser que l'éducation des utilisateurs avec de bons usages de la cryptographie les sauverait. La tension ici ne se situe pas entre ceux qui savent et les autres : elle relève à l'heure actuelle de l'absence même d'intégration de la sécurité pour les utilisateurs lambdas. On peut voir néanmoins quelques changements significatifs ces dernières années tel le passage quasi systématique par TLS pour le trafic HTTP.

Prenons l'ensemble des niveaux nécessaires à l'obtention de moyens cryptographiques (des problèmes mathématiques jusqu'aux applications en passant par les protocoles et les librairies) : il y a grosso modo deux approches dans le processus de développement de ces moyens. Celle ouverte (académique ou communautaire) et celle fermée (entreprise privée ou agence gouvernementale). Il n'est pas nécessaire de détailler la seconde approche, ceci pouvant être uniquement fait au cas par cas et parfois difficilement (l'exemple le plus parlant étant les travaux de rétro-ingénierie sur Skype). Reste alors une approche permettant d'être vérifiée, relue, auditée, cassée et réparée par qui le souhaitera, entraînant un processus de sélection plus ou moins efficace de ce qui est bien fait sur ce qui l'est mal.

Bien sûr, la transparence étant un critère politique et non technique, elle ne suffit en rien à fournir de la sécurité. Elle permettra simplement l'assurance, en terme d'intention, de l'intérêt général. À une époque où la surveillance n'est plus ciblée, mais systématique, un tel critère est essentiel. De tels outils existent d'ores et déjà, avec des communautés actives, des logiciels maintenus et audités, utilisant des standards ouverts, des primitives à jour, auquel le grand public peut effectivement faire confiance. Pour ne citer que lui, GnuPG. Mais qu'en est-il du critère technique ? De la nécessité de ressaisir cet outil à l'ère d'une nouvelle menace ?

3. PGP : quelques lacunes parfois oubliées

3.1 Des bons usages

Un des grands problèmes de PGP n'est pas relatif à sa bonne implémentation de la cryptographie, mais aux bons usages qui en découlent. Effectivement, nombreux sont les dommages collatéraux provoqués par une mauvaise configuration ou tout simplement une mauvaise compréhension de l'outil en lui-même : utilisation d'algorithmes dépassés, mauvaise gestion du trousseau de clefs (longueur des clefs, mise à jour des clefs des correspondants, révocations), l'utilisation d'identifiants de clefs (voir 3.3) et même l'usage d'anciennes versions du standard possible grâce au maintien actuel de la rétrocompatibilité. Bons usages qui d'ailleurs sont étendus à ceux du courrier électronique, du fait de la bonne intégration de PGP avec ce dernier. Imaginons : deux correspondants veulent échanger des messages de manière anonyme et confidentielle. Ils utilisent PGP (moyennant les bonnes options pour l'anonymat) et TLS pour garantir la sécurité au niveau du transport du courrier. Cela sous-entend évidemment que le client de messagerie va vérifier la validité du certificat, sinon une attaque par MITM à base de faux serait aisée, et donc dévoiler les champs non chiffrés par PGP. On peut également imaginer des cas plus triviaux : que ferait un utilisateur qui tente d'envoyer un e-mail chiffré qui ne fonctionne pas, car un attaquant change quelques bits dans les messages envoyés ? Possiblement l'envoyer en clair pensant que le chiffrement est le problème.

La sécurité ne peut reposer sur des bons usages prodigués au fur et à mesure de l'évolution du logiciel et de la situation : qui change de sous-clef toutes les semaines ? qui pense à la non-répudiation en utilisant systématiquement PGP ? Qui utilise encore hkp et non hkps ? Bons usages qui d'ailleurs, restent parfaitement abscons à l'utilisateur, car reposant souvent sur des subtilités du monde de la cryptographie.

3.2 Les limites intrinsèques

S'il y a un concept porté à la connaissance du public averti ces derniers mois, c'est bien celui de « Forward Secrecy ». Les échanges utilisant PGP étant asynchrones (e-mail, fichier), il est compliqué de déployer une telle propriété (une proposition laissée sans suite a été déposée à l'IETF en 2001 [3]). Ainsi, après une série d'échanges entre deux correspondants, s'il y a compromission de l'une des clefs des participants, alors l'ensemble des échanges passés, c'est-à-dire l'ensemble des e-mails échangés par exemple, le sera aussi. Un attaquant qui enregistrerait le trafic relatif à des échanges utilisant PGP ne relève plus de l'imagination d'un paranoïaque, le trafic chiffré étant une cible intéressante et le format OpenPGP se laissant très facilement détecter.

PGP est également peu concerné pour ce qui est relatif à l'anonymat. En effet, il intègre systématiquement dans les messages chiffrés l'identifiant de clef du destinataire (RFC4880, section 5.1). Ce qui donne, sur un fichier chiffré à destination d'un certain bob@mail.org (nous utiliserons GnuPG pour les exemples) :

$ gpg file.gpg

You need a passphrase to unlock the secret key for

user: "Bob <bob@mail.org>"

4096-bit RSA key, ID 76543210, created 2012-03-11 (main key ID 01234567)

Bien sûr, une option existe permettant de supprimer l'ajout systématique de cet identifiant. En résulte pour le destinataire que GnuPG essayera l'ensemble des clefs privées du trousseau local (même celles révoquées !) pour déchiffrer le message (ce qui peut générer des messages d'erreur et une incompréhension de l'utilisateur). PGP assure aussi la non-répudiation lors de la signature des messages, caractéristique souvent oubliée du fait que la signature est utilisée majoritairement pour authentifier les correspondants. Seulement cette signature n'authentifie pas mutuellement les correspondants, elle authentifie l'auteur du message pour quiconque souhaitera le vérifier. L'utilisation systématique des signatures par un utilisateur engendre donc l'impossibilité pour celui-ci de démentir d'avoir tenu tel ou tel propos dans ses messages. L'absence de signature ôtant du même coup la possibilité d'authentifier les correspondants sans chiffrement : l'authentification avec signature implique ici la non-répudiation.

Il pourra aussi être utile de vérifier l'ensemble des primitives cryptographiques utilisées, anciennes et nouvelles, tel les désormais tristement célèbres courbes elliptiques recommandées par le NIST, qui du côté de PGP ont déjà fait l'objet d'une RFC (6637).

3.3 Collision sur les key IDs

Dans la rubrique des mauvais usages de PGP par les utilisateurs initiés, nous avons l'utilisation des identifiants de clef. En effet, les key IDs inondent signatures et profils des utilisateurs sur Internet. Cela fait tendance, sérieux et protégé, mais il n'en est rien. Il faut remonter en 1996 pour trouver la première attaque connue contre les identifiants de clefs, célèbre de par son nom, DEADBEEF. L'idée est assez simple : un identifiant de clef est une série de caractères de faible longueur associée à une clef permettant d'être manipulée par un humain. Typiquement, dans les formats OpenPGP version 4, le key ID est définit par les derniers 4 octets de l'empreinte SHA-1 de la clef publique au format OpenPGP (c'est-à-dire contenant des informations telles que la version, la date de création). Ce qui donne par exemple :

$ gpg --list-keys bob | head -n 1

pub 4096R/01234567 2012-03-11

L'espace de ces identifiants étant bien sûr relativement petit (2^32), il est aisé d'effectuer une attaque bruteforce pour obtenir une clef avec un identifiant choisi. Par exemple, on pourrait générer une clef RSA et modifier sa date de création jusqu'à l'obtention du key ID voulu (changer la date de création ne nécessitant aucun calcul, simplement l'accès au champ correspondant dans la clef). C'est ce que fait bruteforce_keyid [4]. Sachant que le nom et l'adresse e-mail d'une clef sont des champs libres, il devient alors facile d'obtenir deux clefs ayant la même allure dans notre trousseau.

$ ./bruteforce_keyid "Bob1 <bob@mail.org>" 01234567
Generating new RSA key
94608000 tries [23250 / sec]
[…]
Found a collision in 33684 seconds! Saved to 01234567.gpg

Les chiffres de ce dernier exemple sont bien réels, il aura fallu dans ce cas-ci un peu plus de 9h pour tomber sur l'identifiant 01234567. Après avoir renouvelé l'opération pour obtenir deux clefs ayant le même key ID, GnuPG lui, se contente de les importer sans avertissement :

$ gpg --import 01234567.gpg.1
gpg: key 01234567: secret key imported
gpg: key 01234567: public key "Bob1 <bob@mail.org>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg: secret keys read: 1
gpg: secret keys imported: 1
$ gpg --import 01234567.gpg.2
gpg: key 01234567: secret key imported
gpg: key 01234567: public key "Bob2 <bob@mail.org>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg: secret keys read: 1
gpg: secret keys imported: 1

Le problème reste bien entendu le même avec des identifiants plus grands, tels les long key IDs. On relèvera que l'idée de base est d'apporter un confort de manipulation des clefs à l'utilisateur en affectant des identifiants simples. Un système de nommage regroupant l'ensemble des bonnes propriétés n'existant pas encore, les key IDs sont encore là. On voit malgré tout, quelques utilisateurs proposer directement l'empreinte SHA1 de leur clef. Comparer deux clefs veut dire comparer l'intégralité de ce qui les compose, pas seulement comparer une partie ou une transformation de la clef. La question est alors de savoir comment les programmes (et les utilisateurs !) interagissent avec tous ces identifiants, s'ils prennent en compte les collisions : GnuPG par exemple, ne prenait pas en compte les long key IDs ainsi que les fingerprints lors du rapatriement d'une clef depuis un serveur jusqu'en 2011 (il tronquait la chaîne pour ne garder que le short key ID). Beaucoup de serveurs de clefs n'utilisent encore que les short key IDs, ou l'on peut encore citer l'outil PGP pathfinder. Tromper un utilisateur avec une fausse clef ne relève donc pas de l'impossible. Voyons maintenant l'une des questions au cœur de l'usage de PGP, à savoir les moyens permettant d'établir une confiance dans l'association entre une clef et l'identité de son propriétaire.

3.4 Les limites du « web of trust »

3.4.1 Anonymat mon amour

Pour rappel, le WoT (« web of trust ») de PGP est un réseau de confiance décentralisé et établi par les utilisateurs. Le concept est relativement simple, la confiance étant située dans le rattachement d'une clef à l'identité de son propriétaire, il suffit pour chaque utilisateur ayant vérifié cette association de dire qu'il fait confiance à la clef en signant cette dernière. L'ensemble des clefs et signatures correspondantes est alors rendu disponible sur un serveur de clefs (public ou privé). Ce modèle de réseau de confiance comporte plusieurs faiblesses. L'une des plus triviales est la quantité d'informations révélée par un tel réseau : qui interagit avec qui, les identités et les dates des signatures. Remarquons enfin qu'à grande échelle, imaginons l'ensemble des utilisateurs du mail, la quantité d'information qu'il faudra maintenir et traiter est tout simplement inenvisageable à la seule fin de fournir une confiance relative dans l'association des clefs et de leurs propriétaires. Nous ne connaissons d'ailleurs que peu de choses sur les limitations des serveurs de clefs actuels : que se passe-t-il si l'on signe quelques milliards de fois une clef ? Si l'on ajoute quelques milliards d'UID à une clef ? Remarquons également que si l'utilisateur met à jour son trousseau de clefs pour rapatrier les nouvelles signatures et les clefs récemment révoquées, il dévoilera potentiellement l'ensemble des personnes avec qui il entretient des correspondances chiffrées. Il est toutefois possible de mettre à jour en temps aléatoire son trousseau de clefs en passant par Tor [5].

3.4.2 Où tu veux, quand tu veux, avec qui tu veux

Un autre point faible est que l'ensemble de ces informations (date, identifiants de clef, nom et adresse e-mail) peut être aisément généré et offre ainsi la possibilité d'effectuer des signatures à base de clef forgée amenant une confusion certaine dans le réseau de confiance. On pourrait même imaginer de forger intégralement un faux réseau de confiance ressemblant à un réseau existant en se basant sur le même principe. Une fois encore, il y a un bon usage de ce réseau de confiance à faire au niveau de l'utilisateur : savoir correctement vérifier l'identité du propriétaire d'une clef donnée, savoir vérifier la chaîne de confiance, la validité des signatures. Reste également l'ensemble des problèmes relatifs à la gestion de la clef par l'utilisateur : révocation de la clef en cas de perte, compromission ou perte du certificat de révocation, sachant qu'une clef est quasi impossible à effacer dans le cas des serveurs publics.

3.4.3 Tu me prêtes tes clefs ?

Un autre point crucial est la récupération de la clef à partir d'un serveur de clefs. En effet, comme nous l'avons déjà souligné, il va falloir récupérer la bonne clef sur la base d'un identifiant (le key ID, le nom d'utilisateur, ou beaucoup mieux, l'empreinte de la clef), et faire confiance au protocole utilisé pour rapatrier la clef qui, dans la majorité des cas, utilise HKP (OpenPGP HTTP Keyserver Protocol) et donc (c'est de l'HTTP !) une communication sans aucune sécurisation. Il est également possible, à l'instar de HTTPS, d'utiliser HKPS, moyennant une fois de plus la vérification des certificats.

3.4.4 Attaque MITM lors de la récupération des clefs

Voyons une possibilité d'exploitation concrète des faiblesses mentionnées. L'attaque va consister à modifier à l'insu de l'utilisateur les clefs qu'il va rapatrier. Nous supposons que l'utilisateur utilisera GnuPG avec HKP et un identifiant de clef quelconque (empreinte SHA1 ou key ID) pour sélectionner la clef voulue. Nous allons effectuer un MITM sur les échanges HKP, et déclencher à chaque requête la génération d'une clef forgée avec les mêmes attributs (nom, adresse, date, key ID) que la clef demandée en utilisant l'ancien format d'OpenPGP. Tout simplement, car dans sa version 3, le key ID d'une clef RSA n'est autre que les derniers 64 bits du module de chiffrement, la génération d'une clef avec un key ID choisi étant alors très rapide (attaque deadbeef). GnuPG se contentera de récupérer la clef ainsi forgée et l'intégrera au trousseau sans prévenir qu'il s'agit d'une ancienne version. L'outil key-steak [6] permet de réaliser une telle attaque (réalisée ici en local sans MITM). Côté attaquant :

$ python ksitm.py

127.0.0.1 - - [01/Jul/2014 14:57:17] "GET /pks/lookup?op=get&options=mr&search=0xC0660AE1 HTTP/1.0" 200 -

Côté utilisateur :

$ gpg --keyserver 127.0.0.1 --recv-key 0xC0660AE1
gpg: requesting key C0660AE1 from hkp server 127.0.0.1
gpg: key C0660AE1: public key "Trolling the Web of Trust" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)

Si l'on vérifie l'empreinte de la clef rapatriée (le fichier k.pubkeyring contenant la clef originale) :

$ gpg --no-default-keyring --keyring ./k.pubkeyring --fingerprint 0xC0660AE1 | grep fingerprint
 Key fingerprint = F85D 933F F63F 4E3E 68A8 DE3C 6074 B1A7 C066 0AE1
$ gpg --fingerprint -a 0xC0660AE1 | grep fingerprint
 Key fingerprint = 3F 22 B7 F6 52 87 6B 53 0E C0 9E 73 4A A0 D0 D9

On constate bien que pour les deux même key IDs nous obtenons deux empreintes différentes.

Une manière de se protéger de cette attaque est l'utilisation de HKPS (sans oublier de vérifier la validité du certificat), de refuser d'utiliser des clefs au format OpenPGP v3 et surtout, d'effectuer une vérification systématique de l'intégralité de la clef reçue (les signatures par exemple, de bons usages une fois de plus).

Conclusion

Ainsi, une bonne utilisation d'un outil tel que GnuPG [7] offre des possibilités solides afin de se protéger d'agences de surveillance trop curieuses. Seulement, l'énergie nécessaire est considérable tant en terme de compréhension que de configuration. On peut voir depuis les dernières années un effort pour ouvrir ces technologies au grand public, avec des initiatives telles que keybase (https://keybase.io) permettant d'offrir un réseau de confiance plus adapté aux usages désormais quotidiens du web 2.0, mais aussi prism.mx (https://prism.mx/) ou encore le désormais célèbre crypto.cat (https://crypto.cat). On pourra s'intéresser également à quelques projets prometteurs encore expérimentaux tels que LEAP (https://leap.se/) ou encore Pond (https://pond.imperialviolet.org/).

Références

[1] http://www.nist.gov/itl/csd/sp800-90-042114.cfm

[2] https://plus.google.com/+TheodoreTso/posts/SDcoemc9V3J

[3] http://tools.ietf.org/html/draft-brown-pgp-pfs-03

[4] https://github.com/micahflee/trollwot

[5] https://github.com/EtiennePerot/parcimonie.sh

[6] https://github.com/coruus/cooperpair

[7] https://help.riseup.net/en/security/message-security/openpgp/best-practices