David Madore's WebLog: Pourquoi je continue à penser du mal de HTTPS

[Index of all entries / Index de toutes les entréesLatest entries / Dernières entréesXML (RSS 1.0) • Recent comments / Commentaires récents]

↓Entry #2453 [older| permalink|newer] / ↓Entrée #2453 [précédente| permalien|suivante] ↓

(mardi)

Pourquoi je continue à penser du mal de HTTPS

Je dois régulièrement expliquer à plein de gens pourquoi mon site n'est pas accessible en HTTPS et pourquoi je continue à ne pas aimer HTTPS : j'avais déjà écrit une entrée à ce sujet, mais d'une part je la trouve mal écrite, et d'autre part il y a beaucoup de choses à y changer maintenant, surtout du fait de l'existence de Let's Encrypt — car à chaque fois que je dis du mal de HTTPS on me répond oui mais Let's Encrypt. Alors oui, l'existence de ce machin est un énorme progrès dans le système mafieux du HTTPS, suffisant pour que j'envisage de m'en servir. Mais il reste que c'est un progrès sur un système aux principes plutôt pourris, au fonctionnement mafieux, aux buts mal définis, à l'architecture mal conçue, et auquel on attribue des vertus qu'il n'a pas. Je veux donc récapituler mes principales objections, qui ne sont pas forcément rédhibitoires (même mises toutes ensembles), mais suffisantes pour me faire juger que ça n'en vaut peut-être pas la peine en tout cas pour un site comme le mien (qui ne suis pas une banque).

J'insiste sur le fait que tout ceci n'est qu'une récapitulation (voire un brain dump), pas un argumentaire bien-formé. Chacun des points ci-dessous mériterait d'être examiné ou documenté soigneusement et, franchement, je n'ai pas le temps de m'en occuper. Il y a donc sans doute beaucoup de préjugés et de choses dont je ne suis pas du tout sûr (du coup, sans doute pas mal d'erreurs), je ne me suis renseigné que minimalement, mais je n'ai vraiment pas le temps d'essayer de me plonger dans ce merdier : normalement je n'aurais pas publié tout ça parce que je n'aime pas publier des choses où je n'ai pris que très peu de temps de vérifier mes renseignements, mais je commence à en avoir marre d'entendre les gens me chanter des variations sur le thème de maintenant que Let's Encrypt existe, il est temps que tu rendes ton blog accessible en HTTPS, souvent avec un ton de reproche.

Je ne vais pas chercher à ordonner les catégories le HTTPS est mal conçu, le HTTPS pose des problèmes, le HTTPS a des limitations et le HTTPS est relié à d'autres choses qui posent elles-mêmes des problèmes (catégories pas forcément exclusives), je fais confiance au lecteur pour retrouver dans quelle boîte ranger chacune des sections qui suit. Je vais sans doute me répéter, aussi, ou séparer des reproches en plusieurs morceaux : ça fait partie du puzzle à rassembler.

Les autorités de certification sont toujours un système mafieux

Par système mafieux je veux dire un système où un site Web doit se mettre sous l'autorité d'un parrain (autorité racine) pour bénéficier de sa protection, le parrain vous faisant payer selon le niveau de sécurité dont vous voulez bénéficier. Tout est absurde dans ce système : il n'est pas possible de se mettre sous la protection de plusieurs parrains (l'allégeance est exclusive) ni pour l'utilisateur d'accorder une valeur différente (si ce n'est tout ou rien) à différents parrains, ni de cumuler plusieurs sources de confiance (comme le fait d'avoir déjà visité le site) ; tous les parrains ne font pas les mêmes efforts de vérification, et par conséquent la protection réellement assurée est, en fait, le minimum de toutes — il suffit qu'un des parrains soit un traître ou un incompétent et tout le système s'effondre jusqu'à ce qu'on trouve moyen de le contenir.

Le nouveau venu Let's Encrypt est un parrain moins rapace que les autres, il distribue sa protection de façon pas trop regardante, mais évidemment, cette protection est minimale : il accorde le certificat à celui qui semble contrôler le domaine de différents points de vérification, ce qui est une vérification faible contre les attaques du type man-in-the-middle. C'est mieux que rien, mais ce n'est pas beaucoup. Tout le HTTPS (ou en tout cas, tout ce qui ne bénéficie pas d'un certificat à « validation étendue », mais ça sert à tout autre chose) est donc aligné sur ce minimum.

Reste qu'en participant à la manie de tout passer en HTTPS, on aide au développement de ce système mafieux qui, même si un des parrains est moins mauvais que les autres, reste un système mafieux. (Comparer avec DANE.)

La protection contre les autorités de certification incompétentes ou corrompues est essentiellement nulle

Ce point recouvre largement le précédent, mais ça vaut la peine de le répéter : la vérification d'un site en HTTPS est faite selon le certificat qu'il présente, qui doit avoir été signé par une autorité racine (ou plus exactement, une chaîne remontant à une autorité racine). Par défaut, aucune vérification n'est faite qu'un changement de certificat, par rapport à une précédente visite, n'est pas suspecte. Il existe certes des outils permettant de faire ce genre de vérification si on y tient, comme l'extension Certificate Patrol pour Firefox, mais dans la pratique ils signalent tant de choses qu'ils ne servent à rien ; il existe aussi un mécanisme pour faire du key pinning, c'est-à-dire exiger que les certificats ultérieurs présentés par le site utilisent la même clé publique, mais ce mécanisme est lourd et peu utilisé (et pas très bien supporté).

Il existe certes maintenant des mécanismes plus ou moins expérimentaux censés combattre certains problèmes systématiques des autorités de certification, mais ça ressemble beaucoup à mettre un emplâtre sur une jambe de bois.

Aucune confiance n'est accordée aux sites déjà visités

Selon moi, la principale protection que doit offrir une infrastructure de clés pour le Web est d'assurer un utilisateur, qui croit visiter de nouveau un site qu'il connaît bien, que ce site est bien le même que lors de sa dernière visite, et notamment qu'il doit lui accorder le même niveau de confiance. Le bon mécanisme pour ce faire est d'enregistrer la clé utilisée par le site, et de contrôler qu'elle ne change pas dans le temps, ou que la nouvelle clé est signée par l'ancienne ; les autorités extérieures, les parrainages, ne devraient jouer qu'un rôle très secondaire dans cette histoire. Pour ce qui est des premières visites, la protection est forcément plus faible : dans ce cas, on comprend qu'il faille faire appel à une autorité extérieure, mais je verrais plutôt celle-ci dans des sources telles que le site depuis lequel on a suivi un lien (la clé publique du site pourrait être incluse dans le lien, ce qui assurerait l'utilisateur que le site sur lequel il tombe est bien celui vers lequel l'auteur du lien voulait le faire tomber), ou les moteur de recherche (un cas particulier du précédent, mais qui pourrait jouer un rôle de confirmation), ou le DNS (voir le point suivant), ou, effectivement, des autorités de certification. Ou une combinaison de toutes ces choses.

C'est une chose de ne pas avois suivi exactement l'architecture que j'envisage ci-dessus (qui n'est pas parfaitement bien définie pour commencer), mais l'architecture qui a été suivie en est tellement absurdement différente qu'on ne comprend pas bien quel pouvait être l'intention des concepteurs à part mettre en place un système mafieux permettant aux parrains de récolter leur pizzo. Quel sens y a-t-il à ce que la seule manière de mettre un site sous HTTPS soit en le faisant certifier par une autorité racine ? Même sans certificat particulier, même sans aucune vérification à la première connexion, on devrait pouvoir avoir au moins la sécurité du chiffrement opportuniste (protection contre les attaquants passifs, ce qui est déjà mieux que rien), plus une vérification du fait que la clé ne change pas.

Ah, en principe il y a les certificats auto-signés. En pratique, les certificats auto-signés génèrent un message d'avertissement extrêmement inquiétant pour l'utilisateur novice, l'encourageant à fuir au plus vite, alors que la sécurité devrait être au moins égale à celle du HTTP. Comment expliquer cela autrement que par le principe : qui ne paye pas le pizzo n'a pas la protection des parrains ?

Sinon, pour donner une valeur aux précédentes visites, il y a le mécanisme du key pinning, qui demande au navigateur de vérifier que la clé n'a pas changé (et de refuser l'accès au site sinon), mais (1) il ne dispense pas de fournir un certificat lors des visites suivantes, ce qui est complètement crétin (il faut toujours payer le pizzo), (2) il est compliqué à mettre en œuvre (et sans doute pas ou mal supporté par Let's Encrypt), et (3) il est extrêmement peu utilisé dans la pratique.

L'autorité de certification comme point individuel de défaillance

La conséquence du rôle obligatoire des autorités de certification dans le HTTPS même pour un site déjà connu de l'utilisateur et ayant promis de ne pas changer de clé, et que si l'autorité de certification défaille (défaut ?), le site ne peut pas fonctionner : c'est un point de défaillance unique.

Ceci me semble particulièrement problématique dans le cas de Let's Encrypt, qui ne délivre à dessein que des certificats de durée extrêmement courte (90 jours ; j'ajoute que je trouve leurs raisons extraordinairement stupides) : si je comprends bien, donc, ça signifie que si Let's Encrypt est rendu incontactable par un déni de service distribué (DDoS) pendant plus de 90 jours, tous les sites Web qui en dépendent deviendront incontactables. Si à l'heure actuelle un DDoS de 90 jours semble vraiment difficile (le maximum connu semble actuellement d'environ 12 jours), le fait d'ajouter un point d'échec complètement inutile qui permette de faire tomber tellement de sites à la fois me semble vraiment irresponsable. Le DNS au plus haut niveau est raisonnablement protégé contre les DDoS (il est en quelque sorte soumis à une tentative de DDoS permanente), mais cette autorité de certification, je n'en sais rien (ils n'ont pas l'air d'avoir publié d'informations à ce sujet).

Mais ce qui m'inquiète plus que le DDoS dans la perspective de passer mon propre site au HTTPS signé par Let's Encrypt, c'est la possibilité qu'ils cessent d'exister et que, du coup, pour maintenir la pérennité des URL en HTTPS, je sois obligé de passer sous la coupe d'un autre parrain mafieux. Le fait que l'un des sponsors de Let's Encrypt soit Mozilla, que j'apprécie beaucoup mais dont je ne donne pas longtemps de l'espérance de vie (surtout avec Google qui cherche plus ou moins activement à les faire mourir), m'inquiète particulièrement à cet égard.

Les insuffisances de Let's Encrypt

Cette section n'a peut-être pas vraiment sa place dans un texte sur le HTTPS en général, mais si mon but est d'expliquer pourquoi je ne passe pas encore à HTTPS, il faut que je mentionne certains des problèmes associés à la solution Let's Encrypt qu'on me propose généralement. La dernière fois que j'avais regardé :

  • il était difficile de mettre en place le key pinning parce que le client officiel générait une nouvelle clé sans fournir de moyen simple de réutiliser l'ancienne (il est possible qu'ils aient rectifié ce problème depuis),
  • ils ne fournissaient pas de moyen d'obtenir des certificats wildcard (je crois comprendre que ce point est en cours de résolution, mais que ça prendra encore plusieurs mois, et je suppose que la preuve de contrôle du domaine sera encore plus lourdingue à mener).

Je crois que je vais au minimum attendre que ces limitations soient clairement levées. (Je n'ai pas envie de demander l'autorisation à Let's Encrypt ou qui que ce soit d'autre pour ouvrir un nouveau sous-domaine de madore.org.)

Le HTTPS ne protège pas contre ce que les utilisateurs s'imaginent

J'en viens à un type complètement différent de critique.

Wikimédia a déployé il y a quelques années le HTTPS sur l'ensemble de ses sites (Wikipédia, Wiktionary, etc.). Posons-nous la question : à quoi sert-il d'avoir de la cryptographie sur un site complètement public comme Wikipédia ? Le contenu de la page https://fr.wikipedia.org/wiki/Paris est complètement public, il n'y a aucun intérêt à le chiffrer. Voici la réponse (évidente) que beaucoup de gens m'ont donné : le but du HTTPS ici n'est pas de protéger le secret des réponses mais le secret des requêtes, autrement dit, ce que je consulte sur Wikipédia.

Malheureusement, je n'y crois guère.

Je n'ai pas regardé de très près, mais je pense que beaucoup d'information fuite simplement par la taille des requêtes et des réponses (rappelons que le HTTPS ne masque pas la taille des informations qui circulent). La taille des URL et des pages sur Wikipédia étant publique, il ne doit pas être difficile de mettre ensemble ces informations pour retrouver les pages consultées elles-mêmes, en se rappelant que chaque page va déclencher le chargement de plein d'autres pages (images, feuilles de style, etc.) : même si toutes ces requêtes sont pipelinées dans une même connexion HTTPS, les navigateurs ont sans doute plein d'idiosyncrasies identifiables au niveau TCP dans leur façon d'émettre les requêtes, et au final je doute fortement que la sécurité soit sérieuse. Une analyse précise demandrait d'étudier la quantité d'information apportée par la longueur de l'URL sur Wikipédia, celle de la page elle-même et celle des pages liées, à mettre en regard avec l'ignorance qu'on a sur le nom de la page et le contenu des headers. Il faut aussi voir s'il y a compression dans l'histoire (j'avais cru comprendre que la compression avait été supprimée dans HTTPS suite à d'autres types d'attaques de fuite d'information que je trouvais d'ailleurs pathétiquement évidentes : ce HTTPS est une perpétuelle fuite en avant devant l'incompétence).

Je n'ai franchement pas envie de fouiller dans cette merde pour essayer de comprendre les choses, mais il y a un principe en crypto, c'est que c'est à celui qui prétend la sécurité qu'incombe la charge de la preuve, et HTTPS n'est tout simplement pas prévu pour offrir cette sécurité-là. (Et de fait, dans la pratique, à chaque fois que quelqu'un prétend oui, ceci est une attaque théorique, mais elle ne marchera jamais en pratique, quelqu'un montre que si.) Bref, il faut considérer que même si vous consultez Wikipédia par HTTPS, un attaquant motivé peut connaître les pages que cous y consultez.

Sur un problème adjacent mais en théorie de l'information, voir : Private Information Retrieval

Je pense qu'il en va vaguement de même des recherches Google à cause des complétions/suggestions automatiques. En regardant la longueur des réponses à chaque lettre tapée au clavier (qui doit se traduire par une requête assez courte), et en comparant avec la longueur des suggestions que Google offre effectivement pour cette lettre, il me semble plausible qu'un attaquant passif qui peut voir passer les requêtes et réponses chiffrées puisse retrouver tout ce que les gens tapent comme recherches avec suggestions automatiques. Peut-être qu'un jour des gens publieront un article médiocre pour le démontrer, ça fera scandale, et Google prendra une mesurette pour contourner ce problème, mais le fond est que HTTPS n'est pas non plus prévu pour protéger ce genre de choses.

En revanche, il y a une chose contre laquelle HTTPS protège effectivement, et qui est pertinente dans le contexte de la consultation de Wikipédia, c'est la modification des données : le HTTPS empêche que le fournisseur d'accès insère des bandeaux publicitaires dans les pages Wikipédia. Mais j'ai bien envie de dire que la réponse à ce genre de problèmes, si on est coincé avec un tel fournisseur d'accès, c'est d'utiliser un VPN (qui passe, lui, par HTTPS) pour avoir une connexion correcte, et de faire du HTTP dessus : l'existence du HTTPS est donc utile (je ne le nie absolument pas), mais pas spécialement pour se connecter à Wikipédia.

Je crois que l'analyse que je fais pour Wikipédia s'applique tout autant, et même encore plus, à un site public comme le mien où ne se trouve aucune information secrète (même le système de commentaires n'a pas vraiment de mot de passe). Bref, autant je ne conteste pas du tout l'utilité du HTTPS pour un site sur lequel on échange vraiment des secrets, autant pour un site public je pense que son intérêt est très douteux.

Et qu'en est-il des caches ?

Le fait de passer des sites publics comme Wikipédia en HTTPS a fini de tuer les caches Web. Vous allez me dire, ils étaient déjà morts. Certes, mais je ne sais pas si c'était vraiment nécessaire d'ajouter un clou supplémentaire à leur cercueil : il y a encore des idées à tirer des mécanismes de cache à une époque où le Web fait un usage immodéré de resources partagées comme les polices ou les bibliothèques JavaScript.

Mais je pense aussi aux caches individuels des navigateurs. Un jour, quelqu'un va finir par se rendre compte qu'en faisant des liens <iframe> invisibles (ou équivalent : requêtes JavaScript, que sais-je) vers des pages Wikipédia et en regardant la taille des réponses, il peut savoir si l'utilisateur a déjà consulté ces pages, ce qui est une évidence contre laquelle HTTPS n'est pas censé protéger, mais parmi les gens qui s'imaginent que passer Wikipédia en HTTPS était une bonne idée, ce qui continue à me laisser perplexe, certains vont crier comme des putois en entendant parler de cette attaque, et demanderont que les navigateurs désactivent complètement leurs caches en HTTPS, pour protéger la vie privée des utilisateurs, ou quelque sottise de ce genre. Et en un certain sens, ils n'auront pas tort : une fois qu'on commence à s'imaginer que ça a un intérêt de chiffrer des informations publiques comme Wikipédia, c'est qu'on veut protéger autre chose que ces informations, et les contours de cet autre chose sont tellement flous et susceptibles de tellement d'attaques (c'est la deuxième que j'évoque, toujours autour de la taille des requêtes/réponses) que les mesures les plus bizarres s'imposent.

Le fiasco des cookies tiers, et autres crottes de ragondins

J'ai mentionné au passage ci-dessus les attaques de type CRIME/BREACH. Le point qui suit n'a pas vraiment de rapport avec HTTPS, mais il faut bien le mentionner dans ce contexte.

Les requêtes tierces sont une plaie. Par requête tierce, je veux dire, n'importe quelle requête vers un site X qui peut être provoquée ou contrôlée par un site Y, ou, pour prendre une définition plus fonctionnelle, lorsque la barre d'adresse du navigateur affiche autre chose que le domaine de X. Par exemple, si je lie depuis mon blog vers une image hébergée par Wikipédia, cela provoquera une requête tierce (la consultation de mon blog Y provoque le chargement d'une image sur X=Wikipédia). Les requêtes tierces ne posent pas de problème particulier de confidentialité lorsque tout est public dans la requête et la réponse (il peut toujours y avoir des problèmes de sécurité, comme la possibilité de mener des attaques DDoS, mais ceci est complètement autre chose). Mais dès qu'il commence à y avoir échange, dans la requête tierce elle-même ou dans sa réponse par le site X, d'informations qui ne sont pas connues de Y (typiquement : cookies identifiant le visiteur auprès de X, ou page personnalisée selon ces identifiants ; ou simplement, présence d'informations en cache), c'est la porte ouverte à toutes sortes de problèmes. Je n'ai pas cessé de le répéter : ces requêtes ne devraient tout simplement pas être autorisées, et dès lors qu'on les autorise, les problèmes de sécurité ne cesseront jamais ; en ignorant cet avertissement, on s'est exposé à des problèmes évidents, comme les attaques BREACH (les longueurs des requêtes ou réponses, si elles sont comprimées et que la requête est au moins partiellement contrôlée par l'attaquant, peuvent servir d'oracle pour dévoiler le contenu des secrets) ou le fait (qui n'a rien à voir avec HTTPS mais avec CSS) que le site Y peut faire des liens vers X et interroger le navigateur pour connaître la couleur de ces liens pour savoir s'ils ont déjà été visités ; ces problèmes ont été corrigés — plus ou moins — peut-être — partiellement — mais il est évident qu'il en surviendra d'autres tant que le problème n'aura pas été corrigé à la racine.

La solution que je préconise est la suivante : lorsque le navigateur affiche dans une barre d'URL une adresse du domaine Y, il doit se fermer toute information relative au site X (les cookies de X doivent être inaccessibles, mais même, pour continuer de mettre des clous dans le cercueil des caches, toutes les pages de X qui sont dans le cache et jusqu'à la simple liste de celles-ci). En fait, le navigateur doit se comporter comme s'il y avait un navigateur (ou du moins, un profil) hermétiquement séparé pour chaque domaine de sécurité. (En plus de ça, la requête devrait contenir un en-tête avertissant le site X que la requête n'émane pas de son propre domaine — sans, bien sûr, lui donner l'information du domaine dont elle émane effectivement.)

Des bouts de cette solution ont été implémentés, mais de façon incohérente. La séparation des domaines est faite a posteriori, au fur et à mesure que des problèmes sont découverts. Le problème est que les utilisateur sont devenus accros des liens de partage sur les réseaux sociaux (vous avez aimé cette histoire ? cliquez ici pour partager sur Facebook) qui seraient rendus impossibles par la solution que je préconise au paragraphe ci-dessus. Même pour ceux qui s'en foutent de pouvoir partager sur Facebook en un seul clic, je ne crois pas qu'il existe de solution vraiment satisfaisante de séparation de domaines (à part avoir un profil de navigateur séparé pour chaque site qu'on consulte, ce qui est essentiellement équivalent à la suggestion que je fais) : je crois désactiver les cookies tiers dans Firefox, par exemple, n'est pas tout à fait équivalent pour une raison que j'eus cru comprendre mais que j'ai maintenant oubliée.

Comme je le disais, tout ceci n'a pas vraiment de rapport avec le HTTPS. Mais la raison pour laquelle je mentionne quand même dans ce contexte est que ça doit nous amener à réfléchir sur ce qu'est une requête publique. Dans le cadre de la solution de séparation complète des domaines que je décris ci-dessus, il n'y aurait aucun sens à chiffrer des requêtes tierces : une requête tierce ne devrait être autorisée que lorsque tout est public (la requête comme sa réponse), donc il n'y a rien à protéger par du chiffrement — si on avait adopté ce point de vue, on n'aurait jamais commis les erreurs conduisant aux attaques du type BREACH. En revanche, ce qui aurait un sens, c'est de protéger l'intégrité des réponses aux requêtes tierces, c'est-à-dire pour le site Y de dire : la réponse fournie par le site X doit avoir le haché <machin>, ou : doit être signée par la clé <truc>. Mais le HTTPS confond protection contre l'écoute et protection d'intégrité, donc on ne s'en sort pas.

Les problèmes de configuration

On s'attend peut-être à ce que je me plaigne du surcoût du HTTPS en temps processeur (ou des émissions de CO₂ provoquées ?) mais non, soyons sérieux, je n'ai pas vraiment ça en tête. En revanche, le surcoût en complexité d'administration et donc en temps humain me préoccupe plus.

Alors certes, les choses sont plus favorables qu'autrefois : maintenant, au moins, HTTPS fonctionne (dans l'immense majorité des cas) : il a fallu attendre l'extension SNI pour qu'il soit possible d'utiliser HTTPS sur un serveur Web servant plusieurs domaines séparés par nom, ce qui est le cas de l'immense majorité des serveurs. Mais le fait que ça fonctionne ne signifie pas que ce soit facile pour autant.

La configuration d'Apache (ou tout autre serveur Web) reste délicate. Il y a beaucoup plus d'options à configurer pour mettre en place un site HTTPS qu'un site HTTP, des paramètres ayant rapport au fonctionnement fin de SSL, aux chiffrements et options à activer, à la compatibilité ascendante ou à l'évitement de certaines faiblesses de sécurité (SSLCipherSuite, SSLProtocol, ssl-unclean-shutdown, downgrade-1.0, Strict-Transport-Security, Public-Key-Pins, X-Frame-Options ? que de choses auxquelles réfléchir et se demander est-ce que je veux vraiment garder le défaut ?). Et ça, c'est sans parler des certificats eux-memes : non seulement le format des certificats est merdique au possible et les outils pour les manipuler sont tout aussi merdiques, mais il faut s'occuper de distribuer les certificats aux différents serveurs (et il y a des brimades assez gratuites : à ma connaissance, il faut faire faire un reload à Apache si on change le fichier de certificat, il n'est pas assez malin pour contrôler son timestamp et décider lui-même de le recharger s'il a changé : pourquo tant de haine ?).

À ces additions de complexité par rapport à un site HTTP s'ajoute l'obtention des certificats. Cette difficulté varié selon le mécanisme qu'on a choisi, mais comme je l'ai mentionné, Let's Encrypt fournit des certificats valables seulement 90 jours (plutôt que, disons, 10000 ans) pour la raison expressément annoncée de vous emmerder au maximum, c'est-à-dire de vous obliger à tout automatiser, ce qui veut dire faire tourner un nouveau service et une panoplie de scripts obscurs sur vos serveurs, avec toutes les difficultés liées à l'installation de ce service, à commencer par comprendre ses options, qui ne sont pas peu nombreuses et comment il interagit avec le serveur Web (il doit pouvoir répondre à des challenges de Let's Encrypt ce qui implique une interaction dans un sens, et ensuite mettre en place les certificats ce qui implique une interaction dans l'autre). Et avec tout ça, le client fourni par Let's Encrypt n'est peut-être toujours pas capable de faire commodément du key pinning.

Rien de tout ça n'est insurmontable, sans doute, mais c'est le genre de choses qui me fait dire que l'informatique est très forte pour résoudre de façon compliquée les problèmes qu'elle a elle-même mis en place. Déjà je me suis pas mal arraché les cheveux à mettre en place le serveur Tomcat qui sert les pages individuelles des entrées de ce blog (parce que Java semble, ou en tout cas semblait quand je me suis renseigné, être à peu près le seul langage capable de parser le XML correctement), et mettre en place la communication entre Apache et Tomcat, alors l'idée de rajouter une couche de communication pour que Tomcat comprenne qu'Apache a reçu une connexion par SSL m'enchante franchement assez peu. Ajoutez à ça que j'ai plusieurs serveurs qui servent le même domaine à l'identique (ça me sert pour mener des tests) et je soupçonne que ce sera à moi de me débrouiller pour distribuer les certificats SSL.

Il n'y a pas que la configuration qui est rendue plus difficile, il y a aussi le debug. Je ne vais pas m'étendre là-dessus, mais je donne quand même une information pour fournir laquelle plusieurs espions Bothan sont morts : la variable d'environnement SSLKEYLOGFILE permet de spécifier un fichier dans lequel Firefox ou Chrome sauvegarderont les clés de session SSL, ce qui permet, ensuite, d'examiner et de déchiffrer le trafic réseau avec quelque chose comme Wireshark. Ceci (en plus de l'onglet Network dans les outils développement de Firefox) permet parfois de diagnostiquer certains problèmes. Je ne connais pas d'équivalent côté serveur, cependant (comment demander à Apache d'enregistrer les clés de session utilisées pour toutes les connexions qu'il reçoit ?).

La sécurité enfants du HSTS (ou : comment les navigateurs empêchent leurs utilisateurs de garder le contrôle)

Je mentionnais plus haut que, si on crée un site accessible en HTTPS avec un certificat auto-signé (ce qui n'apporte certes aucune sécurité supplémentaire par rapport au HTTP contre les attaques man-in-the-middle, mais en apporte néanmoins contre les attaques passives, ce qui n'est pas rien !), l'utilisateur reçoit un message d'avertissement extrêmement anxiogène. Mais au moins cet avertissement est-il contournable : il y a un lien (enfin, chez Firefox, je n'ai pas vérifié chez Chrome) pour ajouter une exception et autoriser le certificat (et s'il change, on aura de nouveau un avertissement, ce qui est bien la manière dont je pense que HTTPS devrait fonctionner).

Il en va tout autrement quand un site demande la HTTP Strict Transport Security : et ce n'est pas juste le fait de Firefox, puisque ce comportement est exigé par la sécification du HSTS :

[§12.1] Failing secure connection establishment on any warnings or errors (per Section 8.4 ("Errors in Secure Transport Establishment")) should be done with "no user recourse". This means that the user should not be presented with a dialog giving her the option to proceed. Rather, it should be treated similarly to a server error where there is nothing further the user can do with respect to interacting with the target web application, other than wait and retry.

Mais quelle bande d'enflures que ceux qui ont pris cette décision. Puissent-ils être affligés de pustules et condamnés dans l'au-delà à errer et calculer des SHA-512 à la main jusqu'à trouver une préimage de 4a65207375697320756e6520656e666c757265206574206a65206dc3a9726974652064e28099c3aa747265206166666c6967c3a92064652070757374756c6573 !

C'est ce que j'appelle le raisonnement sécurité enfants : interdire à l'utilisateur de contrôler ses propres logiciels en arguänt qu'on protège ainsi sa sécurité. C'est l'exact opposé de l'esprit Unix qui est de laisser l'utilisateur se tirer une balle dans le pied (ou lui donner assez de corde pour se pendre, si on préfère cette métaphore-ci). Firefox (et Chrome, mais ça ne m'étonne pas de lui) sont très friands de sécurité enfants : Firefox s'est récemment mis, par exemple, à interdire les extensions qui ne soient pas signées par eux — ce qui me pose vraiment un problème étant donné que j'ai plein d'extensions personnelles que j'ai écrites pour moi seul et que je ne veux ni publier ni montrer (pour l'instant, le fait de mettre xpinstall.signatures.required à false fonctionne dans des cas que je ne comprends pas bien, mais ils ont promis que ça ne durerait pas indéfiniment). On commence à se croire chez Apple.

Et le fait de vouloir outrepasser la sécurité HSTS n'est pas forcément le fait de quelque chose d'excessivement louche. Ça peut même être une façon de vouloir augmenter sa propre sécurité : par exemple, si je ne souhaite pas faire confiance à l'autorité racine qui a signé les certificats que présente tel ou tel site (voir ce fil où un utilisateur a du fil à retordre à cause de HSTS) ou pour toutes sortes d'autres raisons listées dans la RFC 6797 elle-même (§14.5 et §14.9).

Noter que je ne suis pas du tout contre un compromis. Par exemple, que la sécurité enfant soit activée sauf si on lance le navigateur avec --expert-mode --yes-i-really-want-expert-mode --yes-i-realize-that-expert-mode-will-turn-off-child-safety-features et qu'il s'affiche un avertissement (du genre qui ferait peur à Madame Michu) annonçant qu'on est en mode expert et que c'est très dangereux si on ne sait pas exactement ce qu'on fait, et que si on a fait ça en suivant les conseils d'un site Web on ne devrait pas. Mais faire plus que ça est vraiment de l'abus.

Alors certes, Firefox est un logiciel libre, je peux désactiver la sécurité enfants si je suis assez malin pour trouver où elle est dans le code. J'avoue que ce n'est pas le cas : le fait d'être vaguement compétent pour savoir que je peux vouloir désactiver HSTS ne signifie pas que je le sois pour fouiller dans les dizaines de millions de lignes de code qui constituent Firefox. J'ai trouvé l'existence du fichier SiteSecurityServiceState.txt, ce qui est déjà intéressant, mais ça ne permet pas tout.

Remarquez au passage que la §11.3 de la RFC 6797 est vraiment du foutage de gueule dans les grandes largeurs, une façon de prétendre qu'on peut profiter du HSTS sans passer par la mafia des autorités de certification alors que cette section est, quand on regarde de près, totalement vide de contenu (ou que ce qui tient lieu de contenu ne marche tout simplement pas).

La stabilité des URL

Voici ce que, finalement, je considère comme le plus important. Le problème est que le protocole, http ou https est écrit dans l'URL. Si j'avais conçu la chose, l'URL commencerait toujours de la même manière, le client essaierait d'abord d'effectuer une connexion chiffrée, et, s'il n'y parvient pas (et sauf si un mécanisme comme HSTS lui interdit la dégradation), il descendrait à une connexion non-chiffrée, avec indication claire dans l'icône pour montrer à l'utilisateur que c'est le cas (et bien sûr, interdiction d'accès aux cookies qui ont été positionnés en mode chiffré, etc.). Le fait de spécifier le mode de connexion dans l'URL n'aurait véritablement de sens que si on pouvait aussi fournir une empreinte de clé (ou un haché de contenu) dans l'URL, possibilité que j'ai déjà évoquée plus haut.

Et le problème avec cette séparation des protocoles est que cela crée des changements massifs d'URL stables. Il se trouve que je suis particulièrement vigilant à la stabilité des URL : l'adresse de mon site Web est http://www.madore.org/ — avant, c'était http://www.eleves.ens.fr:8080/home/madore/ (et j'ai dû me battre pour conserver ce :8080 et me battre encore plusieurs fois pour conserver cette redirection qui continue à marcher à l'heure où j'écris) — le changement a été assez douloureux quand j'ai dû décider adresse par adresse quoi changer et quoi laisser, et je n'ai pas envie de changer une nouvelle fois pour https://www.madore.org/ ; et si je le fais je veux avoir une certitude assez forte que je pourrai maintenir ce domaine, que ne m'offre pas Let's Encrypt puisque je ne suis pas sûr de sa stabilité à lui (cf. ci-dessus).

Mais ce n'est pas qu'une considération théorique. Régulièrement, un site que je visite décide de passer de http à https, et ça casse plein de choses. Certes, ça ne casse pas les liens eux-mêmes parce qu'ils sont généralement redirigés (il faudrait vraiment que le site fasse très mal sa redirection pour que ce ne soit pas le cas), mais ça casse des choses plus subtiles.

Voici un scénario typique : je rend souvent visite au site http://www.bigfatdildos.tld/, celui-ci décide de passer en HTTPS et devient donc https://www.bigfatdildos.tld/. Mais la manière dont j'accède au site consiste à commencer à taper le nom dans la barre d'adresse (la awesome bar) de Firefox, qui me propose alors la complétion qui va bien ; la raison pour laquelle j'arrive sur le bon site est que je rends souvent visite à ce site et qu'il est donc tout en haut dans les suggestions. Le jour où ils passent à HTTPS, il se met à y avoir deux sites bien distincts pour ce qui est de Firefox : un site HTTP, qui ne fait que rediriger vers HTTPS, et le site en HTTPS, qui est « le bon » ; mais le site qui est connu dans les suggestions est celui en HTTP. À partir de là, je ne comprends pas très bien ce qui se passe, mais le fait est que le site apparaît beaucoup moins bien dans les suggestions dans ses deux variantes : probablement, le site HTTP reste en premier parce qu'il a beaucoup de visites cumulées passés mais n'est pas compté comme recevant de nouvelles visites car tous les liens que je suis vont me mener vers le site HTTPS, celui-ci finit par monter aussi, mais comme il n'a pas de visite directe tapée à la main, il ne monte pas tant que ça, bref, il me semble que les deux se retrouvent généralement à un rang assez médiocre. Si je supprime toutes les versions en HTTP des suggestions de complétion, le site HTTPS est quand même tout nouveau et il lui faut beaucoup de temps pour remonter dans les fréquences.

Et il n'y a pas que des questions de rang dans les suggestions : le doublon HTTP/HTTPS pollue mes suggestions de complétion, parce que beaucoup de choses apparaissent en double, ce qui divise du coup en gros par deux l'utilité de la awesome bar (sur N résultats affichés, il n'y en a en fait vraiment que ½N).

Il y a aussi des problèmes avec les icônes de site (favicons), que je ne comprends pas très bien, mais l'idée générale est qu'au moinde problème réseau, la version HTTP du site va se retrouver avec une icône du genre « réseau cassé », qui ne sera jamais corrigée parce que ce n'est qu'une redirection vers la version HTTPS et le site HTTP lui-même n'a pas de vraie icône (donc Firefox garde la dernière connue). Quelque chose comme ça.

Quant aux bookmarks, ils posent en gros les mêmes problèmes. Plus d'une fois, j'ai édité un bookmark pour remplacer http par https, et Firefox Sync m'a fait me retrouver avec deux versions du même site dans mes bookmarks, une en HTTP et une en HTTPS.

Vous direz, tout ça ce sont des problèmes avec Firefox, pas avec HTTPS. C'est sans doute vrai, mais le fait de mettre le protocole dans l'URL rendait ce genre de problèmes assez inévitables. Une URL est censée être un identifiant stable et fixe vers une resource : si on la change, même avec une redirection, il y a plein de petites merdes de ce genre qui apparaissent.

Pour Wikipédia, j'en suis extrêmement mécontent. J'avais tout un système de scripts qui me permettait de mémoriser et faire des statistiques sur les pages que je consultais régulièrement sur Wikipédia (ça avait commencé ici), ils ont été cassés par le passage à HTTPS dont je continue à juger qu'il ne servait absolument à rien s'agissant d'un site public. Du coup, j'ai mis fin à mes contributions à Wikipédia (mes dernières contributions sont une demande d'aide pour régler le problème, les réponses que j'ai obtenues ont fini de me convaincre que je n'aimais décidément pas les gens qui investissent du temps dans l'administration de ce projet). Je reprendrai si et quand je trouve un moyen de régler tout ce merdier : en attendant, j'ai autre chose à faire que de me battre avec ces moulins à vent. Si par hasard quelqu'un connaît un miroir de Wikipédia en HTTP (qui permette aussi d'éditer !) vers lequel je pourrais faire pointer wikipedia.org au niveau de mon serveur DNS (en désactivant HSTS au niveau du navigateur), ça m'intéresse, faites-moi signe.

La question reste quand même de savoir quel est la bonne URL à utiliser quand on veut faire un lien vers Wikipédia. J'ai choisi de les faire en http parce que je n'ai pas vraiment envie de revenir en arrière sur des centaines et des centaines d'entrées de blog et les modifier pour pointer vers la nouvelle adresse, mais aucune solution n'est satisfaisante, et c'est bien le genre de choses qui me pose problème.

Je devrais sans doute aussi mentionner le fait que les sites HTTP et HTTPS ne sont pas toujours équivalents. Par exemple, j'ai longtemps utilisé sur ce blog des liens vers Google Images sur le modèle http://images.google.com/images?q=terms+to+search+for, ces liens fonctionnent correctement (exemple ici), mais ils ne fonctionnent plus si on remplace http par https, ce qui m'a valu des bug-reports incompréhensibles tes liens vers Google Images sont cassés — enquête faite, le problème était que ces gens utilisaient HTTPS Everywhere. Ce n'est pas la faute de HTTPS, bien sûr, je vous laisse décider si c'est celle de Google ou de HTTPS Everywhere, mais en tout cas ce n'est pas la mienne, mes liens étaient corrects, et c'est un exemple du genre de confusions qui peuvent apparaître à cause de ce double jeu d'adresses en HTTP et HTTPS.

Ceux qui sautent sur leur chaise comme des cabris en disant Crypto ! Crypto ! Crypto !

Il va de soi (mais ça va mieux en le disant) que je n'ai rien contre la crypto. J'en ai, en revanche, contre l'espèce de manie de crypto qui tient lieu de réflexion sérieuse sur l'opportunité d'en faire usage, et que je tiens pour principale responsable du déploiement de HTTPS sur des sites qui n'en ont nul besoin (comme Wikipédia).

Je soupçonne que cette manie est une façon de se dire qu'on fait des choses qui sont si importantes et si secrètes qu'elles méritent d'être chiffrées — de fait, la crypto s'en fout de ce qu'on lui donne comme secret à gérer, elle peut servir à chiffrer les codes nucléaires américains comme la liste de vos Pokémons préférés ou des articles de Wikipédia qui sont de toute façon publics : son boulot est de protéger la sécurité des informations, pas de décider ce qui mérite d'être protégé. Mais pour qu'elle puisse faire sens, il faut un modèle d'attaques contre lesquelles on veut pouvoir résister. Or ce modèle d'attaque est précisément ce que n'ont pas, je pense, les maniaques de la crypto qui veulent tout passer en HTTPS juste parce qu'on peut le faire (et quitte à ignorer les problèmes que j'ai évoqués) : au lieu de se donner un but précis (protéger contre telle ou telle attaque) et d'utiliser la crypto comme moyen pour accomplir ce but, ils voient la crypto comme une fin en soi, autrement dit, ils sautent sur leur chaise comme des cabris en disant Crypto ! Crypto ! Crypto !. Mais la crypto ne vous protégera contre rien si vous ne savez même pas contre quoi vous voulez être protégés.

Conclusion

Pour l'instant, s'agissant de mon propre site, je ne fais rien. Mon serveur n'écoute même pas sur le port HTTPS. Déjà j'ai du mal à trouver le temps de m'occuper du système de commentaires, qui est tout pourri (c'est un vieux script Perl qui ne parle pas du tout au reste du moteur de blog), et qui me semble un problème bien plus urgent que le HTTPS. Même en matière de crypto mettre en place DNSSEC me paraît plus important.

Mais je ne dis pas non plus fontaine, je ne boirai pas de ton eau : quand Let's Encrypt gérera les certificats wildcard (et le key pinning si ce n'est pas déjà le cas), je commencerai à regarder si ce n'est pas trop pénible à mettre en place une version du site en HTTPS — restera à trouver une politique de stabilité des URL (je peux mettre le site en HTTPS et ne publier que des permaliens en HTTP, mais je ne sais pas si ça suffira à éviter que des adresses en HTTPS s'enfuient dans la nature).

↑Entry #2453 [older| permalink|newer] / ↑Entrée #2453 [précédente| permalien|suivante] ↑

[Index of all entries / Index de toutes les entréesLatest entries / Dernières entréesXML (RSS 1.0) • Recent comments / Commentaires récents]