Déjouez les attaques de l'homme du milieu avec HTTPS et HTTP Strict Transport Security

Compte tenu de la quantité de données personnelles qui circulent sur Internet, le chiffrement n'est pas quelque chose que nous pouvons ou devons ignorer. Les navigateurs récents proposent plusieurs mécanismes permettant de garantir la sécurité des données de vos utilisateurs en transit : les cookies sécurisés et la sécurité de transport stricte sont deux des plus importants. Elles vous permettent de protéger vos utilisateurs de manière transparente, en mettant à niveau leurs connexions vers HTTPS et en garantissant que les données utilisateur ne sont jamais envoyées en clair.

En quoi cela vous concerne-t-il ? Réfléchissez aux questions suivantes :

Diffuser une page Web via une connexion HTTP non chiffrée revient plus ou moins à remettre une enveloppe non scellée à la première personne que vous voyez dans la rue et qui semble se diriger vers la poste. Si vous avez de la chance, elle l'apportera elle-même à destination, ou elle le remettra à la prochaine personne qu'elle verra se diriger dans la bonne direction. Cette personne peut faire de même, et ainsi de suite.

La plupart des inconnus de cette chaîne improvisée sont dignes de confiance et ne jetteraient jamais un coup d'œil à votre lettre ouverte ni ne la modifieraient. Toutefois, plus la lettre change de mains, plus le nombre de personnes ayant un accès complet à la lettre que vous envoyez est élevé. En fin de compte, il est fort probable que le destinataire de votre lettre reçoive quelque chose par la poste, mais la question de savoir si ce quelque chose est le même que celui que vous avez remis au départ reste ouverte. Tu aurais peut-être dû sceller cette enveloppe…

Intermédiaires

Pour le meilleur ou pour le pire, de vastes pans d'Internet reposent sur la fiabilité d'inconnus. Les serveurs ne sont pas directement connectés les uns aux autres, mais transmettent les requêtes et les réponses de routeur en routeur, comme dans un jeu de téléphone arabe géant.

Vous pouvez voir ces sauts en action avec traceroute. La route entre mon ordinateur et HTML5Rocks ressemble à ceci :

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 sauts, ce n'est pas si mal. Toutefois, si j'envoie des requêtes via HTTP, chacun de ces routeurs intermédiaires dispose d'un accès complet à mes requêtes et aux réponses des serveurs. Toutes les données sont transférées sous forme de texte brut non chiffré, et n'importe lequel de ces intermédiaires pourrait agir en tant qu'homme du milieu, en lisant mes données ou même en les manipulant en transit.

Pire encore, ce type d'interception est pratiquement indétectable. Une réponse HTTP modifiée de manière malveillante ressemble exactement à une réponse valide, car il n'existe aucun mécanisme permettant de s'assurer que les données reçues sont _exactement_ les données envoyées. Si quelqu'un décide de mettre mon Internet sens dessus dessous pour s'amuser, je n'ai plus qu'à croiser les doigts.

Cette ligne est-elle sécurisée ?

Passer d'une connexion HTTP en texte brut à une connexion HTTPS sécurisée est la meilleure défense contre les intermédiaires. Les connexions HTTPS chiffrent l'intégralité du canal de bout en bout avant l'envoi des données, ce qui empêche les machines situées entre vous et votre destination de lire ou de modifier les données en transit.

L'Omnibox de Chrome fournit de nombreuses informations sur l'état d'une connexion.
L'Omnibox de Chrome fournit de nombreux détails sur l'état d'une connexion.

La sécurité fournie par HTTPS repose sur le concept de clés cryptographiques publiques et privées. Une discussion approfondie sur les détails dépasse (heureusement) largement le cadre de cet article, mais le principe de base est assez simple : les données chiffrées avec une clé publique donnée ne peuvent être déchiffrées qu'avec la clé privée correspondante. Lorsqu'un navigateur lance un handshake HTTPS pour créer un canal sécurisé, le serveur fournit un certificat qui donne au navigateur toutes les informations nécessaires pour valider son identité en vérifiant que le serveur est en possession de la clé privée appropriée. À partir de ce moment, toutes les communications sont chiffrées de manière à prouver que les requêtes sont envoyées au serveur authentifié et que les réponses sont reçues de celui-ci.

Le protocole HTTPS vous garantit donc que vous communiquez avec le serveur que vous pensez contacter, et que personne d'autre n'écoute ou ne modifie les données en transit. Ce type de chiffrement est une condition préalable absolue pour la sécurité sur le Web. Si votre application n'est pas actuellement diffusée via HTTPS, elle est vulnérable aux attaques. Veuillez le corriger. Ars Technica propose un excellent guide pour obtenir et installer un certificat (sans frais). Je vous recommande de le consulter pour obtenir des détails techniques. La configuration varie d'un fournisseur à l'autre et d'un serveur à l'autre, mais le processus de demande de certificat est le même partout.

Sécurisation par défaut

Une fois que vous avez demandé et installé un certificat, assurez-vous que vos utilisateurs bénéficient de votre travail : migrez vos utilisateurs existants vers des connexions HTTPS de manière transparente grâce à la magie de la redirection HTTP, et assurez-vous que les cookies ne sont transmis que via des connexions sécurisées.

Par ici, s'il vous plaît

Lorsqu'un utilisateur accède à http://example.com/, redirigez-le vers https://example.com/ en envoyant une réponse 301 Moved Permanently avec un en-tête Location approprié :

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

Vous pouvez facilement configurer ce type de redirection sur des serveurs tels qu'Apache ou Nginx. Par exemple, une configuration Nginx qui redirige de http://example.com/ vers https://example.com/ se présente comme suit :

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

Les cookies nous permettent d'offrir aux utilisateurs des expériences de connexion fluides via le protocole HTTP sans état. Les données stockées dans les cookies, y compris les informations sensibles telles que les ID de session, sont envoyées avec chaque requête, ce qui permet au serveur de savoir à quel utilisateur il répond à ce moment-là. Une fois que nous nous sommes assurés que les utilisateurs accèdent à notre site via HTTPS, nous devons également nous assurer que les données sensibles stockées dans les cookies ne sont transférées que via une connexion sécurisée et ne sont jamais envoyées en clair.

La définition d'un cookie implique généralement un en-tête HTTP qui ressemble à ceci :

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

Vous pouvez demander au navigateur de limiter l'utilisation du cookie aux sessions sécurisées en ajoutant un seul mot clé :

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

Les cookies définis avec le mot clé secure ne seront jamais envoyés via HTTP.

Fermeture de la fenêtre ouverte

La redirection transparente vers HTTPS signifie que la grande majorité du temps, vos utilisateurs utiliseront une connexion sécurisée lorsqu'ils seront sur votre site. Cependant, il laisse une petite fenêtre d'opportunité pour les attaques : la connexion HTTP initiale est grande ouverte, vulnérable au SSL stripping et aux attaques associées. Étant donné qu'un pirate de type "man-in-the-middle" dispose d'un accès complet à la requête HTTP initiale, il peut agir en tant que proxy entre vous et le serveur, et vous maintenir sur une connexion HTTP non sécurisée, quelles que soient les intentions du serveur.

Vous pouvez limiter le risque de ce type d'attaque en demandant au navigateur d'appliquer le protocole HTTP Strict Transport Security (HSTS). L'envoi de l'en-tête HTTP Strict-Transport-Security indique au navigateur d'effectuer la redirection HTTP vers HTTPS côté client, sans jamais toucher au réseau (ce qui est également idéal pour les performances ; la meilleure requête est celle que vous n'avez pas à effectuer) :

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Les navigateurs compatibles avec cet en-tête (actuellement Firefox, Chrome et Opera : consultez caniuse pour en savoir plus) noteront que ce site particulier a demandé un accès HTTPS uniquement, ce qui signifie que, quelle que soit la manière dont un utilisateur accède au site, il le visitera via HTTPS. Même si elle saisit http://example.com/ dans le navigateur, elle se retrouvera sur HTTPS sans jamais établir de connexion HTTP. Mieux encore, si le navigateur détecte un certificat non valide (qui tente potentiellement d'usurper l'identité de votre serveur), les utilisateurs ne seront pas autorisés à continuer via HTTP. C'est tout ou rien, ce qui est une excellente chose.

Le navigateur fera expirer l'état HSTS du serveur après max-age secondes (environ un mois dans cet exemple). Définissez une valeur raisonnablement élevée.

Vous pouvez également vous assurer que tous les sous-domaines d'une origine sont protégés en ajoutant la directive includeSubDomains à l'en-tête :

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Allez de l'avant, en toute sécurité

Le protocole HTTPS est le seul moyen d'être un tant soit peu sûr que les données que vous envoyez parviennent intactes au destinataire prévu. Vous devez configurer des connexions sécurisées pour vos sites et applications dès aujourd'hui. Il s'agit d'un processus assez simple qui vous aidera à protéger les données de vos clients. Une fois que vous avez mis en place un canal chiffré, vous devez rediriger de manière transparente les utilisateurs vers cette connexion sécurisée, quelle que soit la manière dont ils accèdent à votre site, en envoyant une réponse HTTP 301. Assurez-vous ensuite que toutes les informations de session sensibles de vos utilisateurs utilisent uniquement cette connexion sécurisée en ajoutant le mot clé secure lors de la définition des cookies. Une fois que vous avez effectué toutes ces opérations, assurez-vous que vos utilisateurs ne tombent jamais accidentellement du bus : protégez-les en vous assurant que leur navigateur effectue la bonne action en envoyant un en-tête Strict-Transport-Security.

La configuration du protocole HTTPS ne demande pas beaucoup de travail et présente d'énormes avantages pour votre site et ses utilisateurs. mais l'effort en vaut largement la peine.

Ressources

  • StartSSL propose des certificats sans frais validés par domaine. Rien ne vaut le sans frais. Il est bien sûr possible de passer à des niveaux de validation plus élevés, à un prix raisonnable.
  • Test de serveur SSL : une fois que vous avez configuré le protocole HTTPS pour vos serveurs, vérifiez que vous l'avez fait correctement en exécutant le test de serveur SSL Labs. Vous recevrez un rapport détaillé qui vous indiquera si vous êtes vraiment opérationnel.
  • L'article récent d'Ars Technica "Securing your Web Server with SSL/TLS" (Sécuriser votre serveur Web avec SSL/TLS) mérite d'être lu pour en savoir plus sur les détails de la configuration d'un serveur.
  • La spécification HTTP Strict Transport Security (RFC6797) mérite d'être parcourue pour toutes les informations techniques sur l'en-tête Strict-Transport-Security que vous pourriez souhaiter.
  • Une fois que vous maîtrisez le sujet, vous pouvez indiquer que votre site ne doit être accessible que via un ensemble spécifique de certificats. L'IETF travaille actuellement sur un projet qui vous permettrait de le faire via l'en-tête Public-Key-Pins. C'est encore un peu tôt, mais c'est intéressant et cela mérite d'être suivi.