Les certificats TLS

Les certificats TLS (Transport Layer Security), anciennement SSL (Secure Sockers Layer), font partie de notre quotidien sans que nous nous en rendions compte ou que nous sachions comment ils fonctionnent. Que ce soit pour de la simple navigation sur internet ou le paiement d’articles sur des sites e-commerce, ils permettent d’assurer un certain niveau de sécurité sur ces transactions.

La sécurisation des échanges sur internet reposant en grande partie sur ces certificats, comprendre leur fonctionnement est essentiel pour les mettre en place correctement lors de la mise à disposition d’une application.

Cet article propose de présenter le fonctionnement basique des certificats TLS, sans rentrer dans les détails liés à l’établissement du handshake TLS ou des mécanismes cryptographiques utilisés. Les exemples ci-dessous sont illustrés avec HTTPS mais les mêmes principes peuvent être appliqués aux autres protocoles se reposant sur TLS.

A quoi servent les certificats TLS

Les certificats TLS permettent de garantir 3 principes de sécurité lorsqu’ils sont utilisés dans les communications entre 2 participants (ex : un navigateur Firefox communiquant avec un serveur web de Google).

La garantie de ces 3 principes n’est valable que si les configurations côté client et côté serveur sont conformes.

Authentification

Dans son utilisation la plus répandue sur internet, les certificats TLS permettent à un navigateur web d’authentifier le serveur avec qui il essaie de communiquer.

Lorsqu’un utilisateur se rend sur https://google.fr via son navigateur Firefox, ce dernier récupère le certificat proposé par le serveur de google.fr, vérifie qu’il est valide et à bien été délivré pour google.fr.

Ce mécanisme, décrit ci-dessous, assure au client (Firefox) qu’il est en train d’établir une communication avec un serveur légitime de l’entreprise Google.

Confidentialité

Une fois l’authenticité du certificat serveur vérifiée, la mise en place de la communication HTTPS (HTTP over TLS) permet d’établir une conversation chiffrée entre le client Firefox et le serveur de Google.

La garantie de confidentialité assure que seuls les 2 protagonistes (Firefox et Google) seront en mesure de déchiffrer les messages envoyés.

Intégrité

Enfin, la vérification de l’intégrité protège les messages envoyés d’un acteur à l’autre (Firefox vers Google ou inversement) de toute modification par un acteur tiers non autorisé.

Qu’est ce qu’un certificat TLS ?

Avant de définir ce qu’est concrètement un certificat TLS, il est nécessaire de faire un rappel sur la cryptographie asymétrique servant de base aux certificats TLS.

La cryptographie asymétrique (chiffrement RSA par exemple) utilise 2 clés mathématiquement liées permettant soit de chiffrer et déchiffrer un message soit de signer et vérifier la signature d’un message.

Clés privée et publique

Clé publique

Comme son nom l’indique, cette clé publique ne constitue pas un élément secret.

La clé publique permet de :

  • Chiffrer un message
  • Vérifier la signature d’un message signé par la clé privée

Clé privée

La clé privée représente un élément secret à ne pas partager.

Elle permet de :

  • Déchiffrer un message chiffré avec la clé publique
  • Signer un message

Composition d’un certificat

Un certificat TLS est composé d’une clé publique et d’un ensemble d’attributs relatifs au certificat lui même (ex : date d’expiration), au site web (ex : DNS associés au certificat), à l’autorité de certification émettrice du certificat, etc.

Cet ensemble de données (clé publique + attributs) est signé par la clé privée d’une autorité de certification, ce qui constitue un certificat. La signature assure l’intégrité des éléments composant le certificat. En cas de modification d’un des attributs du certificat, l’opération de validation de la signature échouera.

Certificat

Il est important de noter qu’un certificat ne contient pas de données privées (clé privée). La clé privée reste protégée sur les serveurs du site web proposant un certificat TLS.

Ci-dessous, un extrait du certificat proposé par google.com :

Certificat Google

La chaîne de certification

Comme évoqué ci-dessus, un certificat est un ensemble d’informations (clé publique + attributs) signé par la clé privée d’une autorité de certification.

Une autorité de certification étant également représentée par un certificat et une clé privée, il est possible de construire une hiérarchie d’autorités de certification pour segmenter la distribution de certificats. Seule l’autorité de plus haut niveau (root CA) n’est pas signée par une autre autorité et doit être enregistrée en tant qu’autorité de confiance par le client.

Diviser une autorité de certification en plusieurs autorités de certification intermédiaires peut permettre de segmenter la distribution des certificats par usage. Il est par exemple possible de dédier une autorité intermédiaire à l’émission de certificats pour l’Europe et une autre autorité intermédiaire pour les certificats destinés à l’Asie, ou encore en fonction des types de certificats émis ou des algorithmes cryptographiques utilisés.

En cas de compromission d’une des autorités intermédiaires, grâce à cette séparation, seuls les certificats émis par cette autorité ne sont plus dignes de confiance et doivent être révoqués puis renouvellés.

Hierarchie de certificat

Lorsqu’un client, par exemple Firefox, souhaite vérifier la validité du certificat récupéré lors de la navigation vers une page de google.com, il doit vérifier plusieurs éléments :

  • Il vérifie que la date d’expiration inclue dans le certificat n’est pas expirée ;

  • Il remonte la chaîne de certification jusqu’à l’autorité de certification root en vérifiant les signatures à chaque étape ;

  • Il vérifie que l’autorité de certification root est bien considérée comme étant de confiance par le système d’exploitation ou pas son propre mécanisme de gestion des certificats.

    Les systèmes d’exploitation sont livrés avec une liste d’autorités de confiance établie et qui peut évoluer au fil des mises à jour. Les autorités de confiance doivent faire un certains nombre de validations sur la possession réelle d’un site web avant de délivrer un certificat pour celui-ci.

    N’importe qui ne peut pas acheter un certificat pour google.com.

  • Il vérifie que le certificat n’a pas été révoqué auprès des CRL ou via OCSP.

    L’autorité de certification ayant émis un certificat peut décider de le révoquer en mettant à disposition des clients une liste des certificats révoqués (CRL) ou un répondeur OCSP.

Chaine de certification

Certificat auto-signé

Dans le monde du développement, il est fréquent de parler de certificat auto-signé. Ces certificats, pouvant être générés facilement sur un poste de développement avec des outils comme openssl, ne sont signés par aucune autorité de certification.

Cette absence d’autorité de certification de confiance implique une facilité de falsification. Ne jamais faire confiance à un certificat auto-signé que vous n’avez pas vous même créé.

Cas d’utilisation

Cas normal

Dans un cas normal, un site web légitime acquiert un certificat auprès d’une autorité de certification (Digicert, GlobalSign, etc.) reconnue comme étant de confiance par les systèmes d’exploitation et navigateurs du marché.

Lorsque l’utilisateur tente d’accèder au site web légitime, il récupère le certificat du site web, vérifie sa date de validité, la chaîne de certification, les CRL ou OCSP et enfin que son autorité racine est bien reconnue comme étant de confiance.

Une fois toute ces vérifications faites, le client a authentifié le serveur web, la communication sécurisée peut être établie et les échanges peuvent commencer.

Usage normal

Man in the middle

Lorsqu’une personne malveillante souhaite se placer entre l’utilisateur et le site web légitime, il peut mettre en place un proxy HTTP qui intercepte les requêtes entre les 2 protagonistes légitimes.

Comme évoqué au début de l’article, le TLS apporte une garantie sur l’authentification du serveur web, la confidentialité et l’intégrité des échanges. Un proxy HTTP au milieu d’un tel échange ne verrait qu’un flux chiffré d’informations sans avoir la possibilité de les déchiffrer ou de les modifier.

Pour rendre ces échanges lisibles et modifiables, le pirate doit établir une connexion entre l’utilisateur et son serveur proxy puis entre son serveur proxy et le site web légitime.

Avec le site web légitime, il n’y a pas de problème puisque le serveur proxy agit comme un client classique, le schéma expliqué ci-dessus dans le cas normal s’applique.

Pour que la connexion entre l’utilisateur légitime et le proxy se fasse, le pirate va devoir présenter un faux certificat (émis par une autorité de certification non reconnue) tentant de se faire passer pour un certificat de confiance du serveur web légitime.

Man in the middle

Lorsque le navigateur de l’utilisateur va récupérer le certificat envoyé par le serveur proxy pirate, il va effectuer les étapes de validation décrites précédemment.

Le certificat du proxy pirate n’ayant pas été émis pas une autorité de certification de confiance, cette étape va échouer et un avertissement sera remonté à l’utilisateur.

Avertissement du navigateur

Ci-dessous, un exemple d’avertissement proposé par le navigateur Firefox lors de l’échec de validation de l’autorité de certification root d’un certificat.

Avertissement Firefox

En cas d’acceptation du risque via le bouton “Accept the Risk and Continue”, le navigateur va ajouter l’autorité de certification pirate à la liste des autorités de certification de confiance du navigateur. Ainsi, lors des prochaines vérifications du certificat pirate par le navigateur, l’étape de vérification de l’autorité de certification sera validée et les échanges entre l’utilisateur et le site web légitime seront visibles et modifiables par le serveur proxy pirate et ce sans que ni l’utilisateur ni le serveur web légitime ne s’en aperçoivent.

Exception

Attention donc à ne pas accepter ce risque sans être sûr d’en maîtriser les conséquences.

Côté développement

Quelque soit la technologie utilisée, la plupart des librairies ou outils faisant des appels HTTP intègrent par défaut la vérification des certificats TLS, ce qui peut poser quelques problèmes pour les développeurs.

Sur des API exposées en localhost ou sur des environnements de développement mutualisés, les certificats sont rarement valides et les vérifications faites par les outils échouent, bloquant ainsi l’application.

Pour éviter ces désagréments, les développeurs désactivent la vérification des certificats TLS et peuvent oublier de la réactiver pour l’environnement de production, rendant l’application vulnérable aux attaques du type Man In The Middle.

Voici un exemple en python:

  • On simule du man in the middle avec un proxy HTTP comme Burp qu’on paramètre directement dans le script.
import requests

proxies = {
  'http': 'http://127.0.0.1:8080',
  'https': 'https://127.0.0.1:8080'
}

requests.get('https://google.com', proxies=proxies)

A l’exécution, une erreur apparaît :

╰─❯ python main_1.py
[...]

Traceback (most recent call last):
  File "main_1.py", line 8, in <module>
    requests.get('https://google.com', proxies=proxies)
  File "/home/aymeric/.local/lib/python3.8/site-packages/requests/api.py", line 76, in get
    return request('get', url, params=params, **kwargs)
  File "/home/aymeric/.local/lib/python3.8/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/aymeric/.local/lib/python3.8/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/aymeric/.local/lib/python3.8/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/home/aymeric/.local/lib/python3.8/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='google.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)')))

L’erreur [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain indique bien un problème de validation du certificat.

Si on modifie le script en lui indiquant de ne plus valider le certificat :

import requests

proxies = {
  'http': 'http://127.0.0.1:8080',
  'https': 'https://127.0.0.1:8080'
}

requests.get('https://google.com', proxies=proxies, verify=False)

A l’exécution, python affiche des warnings liés à la désactivation mais ne bloque pas la requête.

╰─❯ python main_2.py
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  warnings.warn(
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  warnings.warn(
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  warnings.warn(

Le contenu de la requête est cependant visible sur le proxy :

Historique HTTP dans Burp

Pour éviter ces risques potentiels de sécurité, plusieurs mécanismes peu couteux peuvent être mis en place :

  • Utiliser une autorité de certification interne à l’entreprise et l’ajouter aux autorités de confiance sur les environnements de développements
  • Si l’environnement le permet, utilisez des certificats émis par Let’s Encrypt.

Quels sont les risques ?

Au sein d’un système, si le protocole TLS n’est pas correctement configuré/utilisé, les risques associés sont les suivants :

  • Fuite de données
  • Altération des données par un tiers

Sans garantie de l’authentification des serveurs et de la confidentialité/intégrité des données, les échanges ne peuvent pas être considérés comme étant de confiance.

Pour aller plus loin

En plus de la bonne configuration/utilisation de TLS, d’autres mécanismes additionnels peuvent être configurés pour apporter une protection supplémentaire :


Voir également