Utiliser HTTPS efficacement pour sécuriser un système IoT

Utiliser HTTPS efficacement pour sécuriser un système IoT

Bien que la multiplication des objets connectés dans les entreprises, les foyers et dans l'espace public représente un risque de sécurité croissant, les outils classiques pour réduire ce risque restent mal connus et souvent mal utilisés. Nous vous proposons donc aujourd'hui une leçon accélérée sur les concepts de base dont vous aurez besoin pour que votre système à base de modules Yoctopuce ne contribue pas à la prolifération d'objets connectés dangereux. Spoiler: il va falloir apprendre à gérer des certificats...

Contexte

La plupart des attaques sur les systèmes informatiques sont perpétrées à distance, sans accès physique à la machine cible: non seulement il est moins dangereux pour l'attaquant de perpétrer son forfait depuis un autre pays, mais plus son cercle d'action est large géographiquement, plus il a de chances de trouver des systèmes mal protégés. Cette discussion sera donc centrée sur la surface de vulnérabilité attaquable à distance: les accès à travers un réseau informatique.

Commençons donc par identifier les canaux de communications qu'on pourrait trouver dans un système IoT à base de modules Yoctopuce. En général, seul un sous-ensemble des éléments ci-dessous est présent, en fonction de l'application, mais les représenter tous sur le même schéma nous permettra de généraliser l'explication à la plupart des scénarios.

Canaux de communications qu'on pourrait trouver dans un système IoT à base de modules Yoctopuce
Canaux de communications qu'on pourrait trouver dans un système IoT à base de modules Yoctopuce


Ce diagramme distingue plusieurs environnements, que l'on traite en général très différemment:

  • Le réseau privé de l'organisation, auquel n'ont normalement accès que les utilisateurs légitimes, et qui est protégé par un pare-feu et/ou un filtre NAT;
  • La DMZ, qui héberge les serveurs accessibles par Internet, et donc la plus à risque. L'entreprise doit néanmoins pouvoir échanger en permanence des informations avec ces serveurs;
  • Le reste d'Internet, dans lequel on retrouve la plupart des utilisateurs, les gentils comme les méchants.

Si la sécurité informatique était sans faille, et si tous les acteurs légitimes du système étaient honnêtes et précautionneux, cette séparation en zones serait suffisante pour protéger l'organisation contre des acteurs malintentionnés venant de l'extérieur par une simple identification des utilisateurs.

Pourquoi introduire la cryptographie

Malheureusement, rien n'est simple. Un réseau WiFi partagé permet facilement à un tiers d'écouter la communication des autres utilisateurs. Des acteurs légitimes peuvent se faire attraper par un message d'hameçonnage et offrir involontairement un accès au réseau privé de l'entreprise à un tiers, ou à un serveur critique. Une faille informatique peut permettre à une personne mal intentionnée de passer une barrière de sécurité (quand il ne s'agit pas simplement d'un système protégé par un mot de passe trivial). Il faut donc prendre des mesures de protection supplémentaires pour anticiper la présence d'intrus.

Les attaques informatiques procèdent en général par palier: une entrée mal protégée vers un système peu critique permet de mettre le pied dans la porte, puis de là l'attaquant peut obtenir des informations lui permettant d'augmenter ses privilèges. La défense consiste donc à cacher les informations sensibles. C'est à ça que sert TLS, utilisé notamment par le protocole HTTPS pour que le navigateur puisse nous annoncer si un accès à une machine est sécurisé ou représente un risque. Alors, comment l'utiliser correctement ?

Principes de TLS

Sans entrer dans les détails des opérations de cryptographie sur lesquels TLS est basé, une connexion sécurisée par TLS signifie qu'elle bénéficie des avantages suivants:

  1. La communication est encryptée de bout en bout, et ne peut donc être lue que par les deux parties communicantes.
  2. La machine qui reçoit la connexion a prouvé son authenticité par un certificat, qui fait office de carte d'identité.
  3. Optionnellement, la machine à l'origine de la connexion peut aussi prouver son identité par un certificat.

A priori, si l'on cherche avant tout à protéger les secrets (mots de passe, etc.), le chiffrement est le bénéfice le plus important. C'est aussi le plus simple à mettre en place: il existe des algorithmes mathématiques qui permettent aux deux parties de se mettre d'accord à distance sur une clé d'encryption commune, sans devoir se la communiquer explicitement, ce qui garantit une communication confidentielle.

Mais le chiffrement ne protège que pour autant que personne ne parvienne à se faire passer pour la machine destinataire. En effet, si un acteur malintentionné (ou un virus) parvient à modifier subrepticement la configuration DNS d'une machine, ou à activer un serveur DHCP malicieux avec d'autres paramètres DNS, les utilisateurs non avertis livreront malgré eux leurs secrets de connexion à un autre serveur, sans que le chiffrement n'y change rien. C'est pourquoi l'authentification du serveur par un certificat est importante pour préserver la sécurité des systèmes, bien que plus compliquée à mettre en place.

Le troisième aspect, l'authentification de la machine à l'origine de la connexion par un certificat (mTLS) est très peu utilisée, car on préfère en général identifier l'utilisateur lui-même, via le canal encrypté, par un ou des secrets qu'il détient personnellement, plutôt que d'utiliser une clé cryptographique stockée sur sa machine.

Comment fonctionne un certificat TLS ?

Un certificat TLS pour un serveur Web est un petit fichier public, qui comporte principalement:

  • une description textuelle du propriétaire légal du certificat
  • une description du serveur Web pour lequel il peut être utilisé
  • une clé publique à utiliser pour vérifier les transactions signées par ce certificat
  • la période de validité du certificat
  • l'identification de l'autorité qui se porte garante de l'authenticité du certificat

Il est intimement lié à un autre petit fichier qui doit lui rester confidentiel: la clé privée de ce certificat.

Lors de l'établissement d'une connexion sécurisée par TLS, le serveur signe l'échange avec sa clé privée, ce qui permet au client de vérifier qu'il est bien en présence du serveur légitime du certificat: il peut vérifier la signature grâce à la clé publique contenue dans le certificat. Mais cela ne prouve l'authenticité du serveur que dans la mesure où l'on est sûr que le certificat est lui-même authentique: un acteur malhonnête pourrait tout à fait créer un certificat valide mais menteur, pour faire passer son faux serveur pour le vrai.

Donc le vrai problème pour sécuriser une connexion vers un serveur n'est pas seulement de lui donner un certificat, c'est de donner aux clients une méthode pour vérifier que le certificat TLS est légitime. La bonne manière de le faire va dépendre du type d'environnement, et du degré de risque contre lequel vous devez vous prémunir.

La méthode naïve, et la solution correcte

La méthode la plus simple serait de transmettre par avance le certificat TLS du serveur au client, idéalement par un canal de transmission indépendant. On pourrait par exemple imaginer d'en stocker une copie dans le logiciel du client, ou dans le cas d'un navigateur Web, garder le certificat TLS lors du premier accès, et l'utiliser pour tous les accès ultérieurs.

Malheureusement, cette solution n'est pas durable, car les certificats TLS des serveurs ont toujours une validité très limitée dans le temps. Pour éviter que le vol d'une clé privée ne compromette indéfiniment une identité, la durée de validité maximale autorisée par les navigateurs pour le certificat TLS d'un serveur Web public est actuellement de 200 jours, et elle sera réduite à 100 jours en mars 2027 et à 47 jours en mars 2029. Chaque client TLS a donc besoin d'une méthode pour vérifier si un certificat TLS jusque là inconnu est authentique.

Ce problème se résoud par la création de chaînes de confiance: le client peut faire confiance à un certificat TLS inconnu si il est signé par un autre certificat parent auquel le client fait confiance. La confiance en ce certificat parent peut elle-même être établie par le fait qu'il est signé par un certificat parent d'un niveau supérieur; on parle alors de certificat intermédiaire. En fin de compte, la confiance repose du client repose sur un certificat racine, qui porte la responsabilité par sa signature de toute une descendance de certificats TLS utilisés par différents serveurs. Or comme le certificat racine n'est utilisé que pour signer d'autres certificats, et non pour établir des connections TLS, il n'a pas besoin d'être directement exposé à Internet. Sa clé privée est donc beaucoup moins à risque. Les certificats racines peuvent donc bénéficier d'une durée de validité bien plus longues, qui se mesure en années.

Voyons comment mettre cela en pratique, en reprenant cas par cas les interactions illustrées dans le diagramme en haut de cet article.

Mise en pratique pour les serveurs publics (zone DMZ)

Pour que le certificat TLS du Serveur Web Public soit reconnu par le navigateur de n'importe quel utilisateur (interaction F dans le diagramme), il faut qu'il soit signé par une organisation dont le certificat racine est inclus dans tous les navigateurs. Chaque navigateur inclut environ une centaine de certificats racines différents, dont la liste officielle est publié sur le site ccadb.org, donc il y a le choix. Mais avant d'opter pour une solution commerciale, sachez que le plus grand émetteur de certificats TLS est une organisation à but non lucratif appelée Let's Encrypt, qui a beaucoup oeuvré pour démocratiser les certificats TLS en offrant une distribution gratuite par un mécanisme d'émission et de vérification entièrement automatisé, appelé ACME. Ces certificats TLS peuvent aussi être renouvelés automatiquement, ce qui est très important vu l'accélération de la fréquence de renouvellement imposée par les navigateurs.

Pour qu'une application basée sur l'API Yoctopuce puisse se connecter de façon sécurisée sur le Serveur Web Public (interaction G dans le diagramme), il faut aussi fournir à l'application le certificat racine qui légitime le certificat TLS du serveur Web Public. A priori le certificat racine ne changera pas à court terme, mais tôt ou tard l'autorité de certification risque de le renouveler, donc il faut nécessairement prévoir un mécanisme de mise à jour de votre application.

Idem pour le (Virtual)Hub Yoctopuce qui se connecte depuis le réseau de l'entreprise vers le Serveur Web Public (interaction D), et vers un Serveur Public Tiers (interaction E): pour une connexion sécurisée, il a besoin de connaître le certificat racine. La version actuelle de VirtualHub-V2 vous permet de passer ce certificat via la ligne de commande, mais pour vous simplifier la vie, nous inclurons dès la prochaine version un jeu de certificats racines à jour, ainsi qu'un mécanisme pour les mettre à jour manuellement si vous le désirez, comme c'est le cas dans les navigateurs.

Mise en pratique sur un réseau privé

Sur un réseau privé, la situation est différente: on ne va en général pas travailler avec une autorité de certification externe, mais le responsable du réseau va créer son propre certificat racine, et pouvoir émettre lui-même ses propres certificats TLS. Lorsqu'il s'agit d'une grande entreprise, cela se fait souvent avec un outil commercial, comme la solution Microsoft AD CS incluse avec Windows Server. Pour une petite organisation il est aussi possible de gérer sa propre autorité de certification avec juste quelques lignes de commande. Vous trouverez dans la section suivate des indications plus précises à ce sujet.

Pour installer dans VirtualHub-V2 le certificat TLS que vous aurez émis, vous pourrez dès la prochaine version utiliser soit un bouton sur l'interface Web, soit la librairie de programmation Yoctopuce ou la librairie en ligne de commande, qui offriront désormais une fonction updateHubCertificate. Cela vous facilitera l'automatisation de la mise à jour des certificats.

De même, pour que votre VirtualHub-V2 puisse se connecter de manière sécurisée à tous vos autres serveurs privés, par exemple un serveur MQTT ou InfluxDB (interaction C sur le diagramme), vous pourrez ajouter votre propre certificat racine à VirtualHub-V2, soit via l'interface Web (manage certificates), soit par la librairie de programmation Yoctopuce ou la librairie en ligne de commande, grâce à la fonction addTrustedCertificate.

Pour que vos propres certificats TLS soient reconnu dans les navigateurs web de votre organisation (interaction A), vous devrez installer votre propre certificat racine chez tous vos utilisateurs. Dans le cas d'une entreprise avec un service de déploiement, cela peut être fait à distance, mais pour une plus petite structure vous devrez simplement transmettre le fichier company_rootcert.crt du certificat racine à tous les utilisateurs, avec les instructions de comment l'installer. Si vous utilisez un navigateur de type Chromium (Edge, Chrome, Opera, etc.), il suffit de l'installer dans le portefeuille de certificats racines de la machine, par exemple avec la commande suivante sous Windows (qui demandera une élévation de privilèges):

certutil -f -addstore "Root" "company_rootcert.crt"


Et au prochain démarrage du navigateur, le certificat sera connu. Si vous utilisez Firefox, ou que vous ne voulez pas installer le certificat globalement sur la machine, ouvrez les réglages de votre navigateur, cherchez-y le gestionnaire de certificat et ajoutez le certificat aux racines de confiance. C'est aussi comme cela qu'il faut procéder si vous voulez rajouter le certificat sur un téléphone portable.

Vous pourrez naturellement facilement intégrer votre propre certificat racine dans vos applications utilisant la librairie Yoctopuce (interaction B). Dans ce cas particulier, vous avez l'avantage de maîtriser à la fois la diffusion de l'application et le moment où le certificat pourrait devoir changer, donc la transition est beaucoup plus facile à gérer: lors d'un éventuel changement du certificat racine, il suffit d'introduire un peu à l'avance le nouveau certificat dans l'application (en plus de l'ancien), pour que le fonctionnement ne soit pas affecté au moment où vous installerez sur le serveur le premier certificat signé par votre nouveau certificat racine.

Créer une mini infrastructure de certification avec OpenSSL

La manière la plus universelle pour créer une mini autorité de certification consiste à utiliser l'outil OpenSSL. Développé à l'origine pour Unix, OpenSSL est maintenant aussi disponible pour Windows sur le repository GitHub officiel de OpenSSL, ce qui nous permettra de vous donner des indication valables aussi bien pour Windows que Linux ou macOS.

Quelques paragraphes ne suffiront pas pour expliquer toutes les subtilités d'OpenSSL: ces exemples de configuration n'ont pas d'autre prétention que de vous mettre le pied à l'étrier, en évitant les erreurs de débutant les plus courantes. Pour plus de détails, référez-vous à la documentation de OpenSSL.

1. Créer le certificat racine de votre organisation

Le premier pas consiste à définir dans un fichier texte rootcert.conf les caractéristiques désirées de votre certificat racine. Dans notre exemple, il s'agit de préciser qu'il est destiné à signer directement des certificats TLS, sans certificats intermédiaires, et de limiter son utilisation aux machines sur le réseau privé. Ainsi, si jamais la clé privée devait être volée, vous ne compromettriez pas l'accès sécurisé à d'autres machines.

basicConstraints     = critical, CA:TRUE, pathlen:0
keyUsage             = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
nameConstraints      = @limitations

[ limitations ]
permitted;IP.0    = 192.168.0.0/255.255.0.0
permitted;IP.1    = 10.0.0.0/255.0.0.0
excluded;IP.0     = 0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0 # not for IPv6
permitted;DNS.0   = .internal # not for public domain names
permitted;email.0 = invalid   # not for e-mail


Vous pouvez alors créer votre certificat racine à l'aide des commandes suivantes:

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256
        -aes-256-cbc -out root.key
openssl x509 -new -key root.key -subj "/O=MyCompany/CN=Root CA"
        -days 3650 -extfile rootcert.conf -out root.crt


Lors que vous lancerez la première commande, vous devrez choisir le mot de passe qui sera utilisé pour encrypter votre clé privée, par sécurité. Choisissez-le soigneusement, et ne le perdez pas: vous en aurez besoin chaque fois que vous utiliserez votre certificat racine. Malgré ce mot de passe, gardez la clé privée (fichier root.key) en sécurité.

Le type de clé (courbe elliptique P-256) que nous vous proposons d'utiliser n'est pas choisi au hasard: il est universellement reconnu depuis 15 ans, offre une protection équivalente à RSA-3072 mais permet des calculs beaucoup plus rapides, ce qui compte sur les systèmes embarqués comme les hubs Yoctopuce.

2. Créer des certificats TLS pour des machines

Maintenant que vous avez un certificat racine, vous êtes votre propre autorité de certification et vous pouvez générer vos propres certificats TLS. Pour cela, la première étape consiste à nouveau par définir dans un petit fichier de configuration host.conf les autorisations accordées aux certificats qui seront créés:

basicConstraints       = critical, CA:FALSE
keyUsage               = critical, digitalSignature
extendedKeyUsage       = serverAuth
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always
subjectAltName         = IP:${ENV::IP}


La syntaxe particulière utilisée pour le subjectAltName nous permettra d'utiliser le même fichier de configuration pour toutes les machines, plutôt que d'en faire un par adresse IP.

On peut alors utiliser le petit script ci-dessous si-dessous pour créer un certificat TLS pour la machine 192.168.0.50:

set IP=192.168.0.50
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out %IP%.key
openssl req -new -key %IP%.key -subj "/O=MyCompany/CN=%IP%" -out %IP%.csr
openssl x509 -req -in %IP%.csr -CA root.crt -CAkey root.key
        -CAcreateserial -days 199 -out %IP%.crt -extfile host.conf
openssl verify -CAfile root.crt %IP%.crt


A vous de personaliser ce script selon vos besoins. Si vous utilisez Unix, remplacez set IP= par export IP=, et remplacez les %IP% par $IP.

Notez que nous avons limité la validité du certificat à 199 jours par analogie aux certificats publics, mais ce n'est pas une obligation pour les certificats émis par un certificat racine d'entreprise.

Ce script générera deux fichiers 192.168.0.50.crt et 192.168.0.50.key que vous devrez installer sur le serveur privé correspondant, par exemple sur VirtualHub-V2 dans notre scénario. Attention, pour que le serveur puisse lire la clé privée, elle est volontairement non chiffrée (sans mot de passe): VirtualHub-V2 se chargera de la sauvegarder lui-même de manière sécurisée. Mais prenez soin d'en effacer toutes les copies de votre disque une fois que le certificat a été installé sur le serveur, vous n'en aurez de toute manière plus besoin (vous pourrez toujours générer un nouveau certificat si nécessaire).

Récapitulatif

Si l'on veut une connexion sécurisée par TLS entre deux systèmes, on doit forcément:

1. Installer un certificat sur le serveur:

  • émis par sa propre autorité de certification si le serveur est sur un réseau privé
  • émis par une organisation comme Let's Encrypt si le serveur est sur Internet

2. Inclure dans les logiciels clients le certificat racine correspondant:

  • soit notre propre certificat racine si le serveur est sur un réseau privé
  • soit le(s) certificat(s) racines de l'organisme qui a fourni le certificat, si le serveur est sur Internet; sachant que si on ne contrôle pas la mise à jour du certificat sur le serveur, on est obligé de fournir un bundle avec tous les certificats publics courants

3. Gérer la distribution et le renouvellement des certificats:

  • le renouvellement du certificat sur les serveurs avant expiration (donc plusieurs fois par an)
  • la distribution du certificat racine de l'entreprise à tous les utilisateurs et son installation
  • la mise à jour des applications en cas de changement du certificat racine


Conclusion

Clairement, tout cela représente un investissement de temps non négligeable, et il faut en mesurer le compromis coût/bénéfice. Pour des applications mineures d'automatisation ou de collecte de mesures non critiques à l'intérieur d'un réseau sécurisé, sans risque d'escalade de privilège, il peut être plus raisonnable de se contenter d'une connexion non sécurisée.

Toujours dans le contexte d'un réseau privé sécurisé, on peut aussi imaginer des demi-mesures pour réduire l'effort tout en préservant le chiffrement fournie par TLS, comme de

  • désactiver la validation de la date d'expiration du certificat serveur dans les applications
  • accepter le certificat auto-signé fourni par défaut par un serveur

Mais il faut réfléchir à deux fois aux conséquences pernicieuses de ces demi-mesures, par exemple en se demandant comment l'application gèrera le jour où le certificat serveur aura vraiment changé. Au final, c'est rarement un bon choix, et il vaut mieux choisir clairement en fonction de l'application entre un canal non sécurisé, ou un vrai canal sécurisé en y consacrant l'effort nécessaire.

Pour rappel, dans un premier temps, nous intégrerons dès la prochaine mise à jour de VirtualHub-V2 un bundle de certificats racines publics pour régler le problème des connections par callback vers les serveurs publics, ainsi qu'une interface et des outils en ligne de commande pour mettre à jour les certificats serveur et racines. On en profitera pour faire un nouvel article de blog qui illustre concrètement avec des screenshots comment mettre tout cela en place.

A terme, pour contrer le surplus de travail causé par le raccourcissement des durées de validité des certificats hôtes, nous allons probablement ajouter le support ACME directement dans VirtualHub-V2, de sorte à ce que vous puissiez mettre en place un renouvellement automatique de vos certificats privés avec un serveur ACME privé.

Dans tous les cas, évitez la fausse bonne idée de bâcler une solution de sécurité: un certificat racine sans limitation avec une clé mal protégée ajoute bien plus de risque à votre entreprise qu'il n'apporte de sécurité.

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.