Un acteur ou sujet (subject) est un membre actif d’un système d’information exerçant une action ou une activité sur les membres de ce système. Les acteurs peuvent être des personnes ou des processus.
Par opposition, un objet est un membre inactif du système d’information sur lequel peut porter une activité exercée par un acteur.
L’identité est la manière dont un acteur d’un système d’information se fait connaitre auprès des autres acteurs de ce système. On rattache à l’identité de nombreuses propriétés ou attributs. Par exemple, on peut citer l’adresse email, le numéro de téléphone, son nom et son prénom, un identifiant d’utilisateur ou d’utilisatrice (User Identifier (UID)), un identifiant de processus (Process Identifier PID), l’appartenance à des groupes, l’attribution de rôles, mais il peut s’agir plus largement de valeurs arbitraires propres à cet acteur.
L’authentification est le procédé par lequel un acteur prouve son identité aux autres acteurs du système. Il existe de nombreuses façons de prouver son identité : mots de passe, clés cryptographiques, biométrie, etc. Dans les textes juridiques, les authentifiants sont parfois appelés “moyens d’identification électroniques”.
L’autorisation encadre les activités que l’acteur peut entreprendre sur les objets du système d’information.
La portée d’une identité peut être vue comme son périmètre d’action, c’est-à-dire l’espace dans lequel cette identité a du sens (un peu comme une carte d’identité française n’a pas de valeur au Royaume-Uni). Nous allons en envisager plusieurs : locale, centrale, répartie et décentralisée.
Une identité peut être locale à un système d’information, ou même à un sous-ensemble d’un système d’information. C’est le cas des comptes locaux gérés par nsswitch et le module PAM (Pluggable Authentication Modules)1 pam_unix
sur une machine Linux. Les identités locales présentent l’avantage d’être autonomes et toujours disponibles, sans être tributaires de la disponibilité de système tiers. La contrepartie est une difficulté notable à maintenir la cohérence des identités sur les différents systèmes, chacun ayant la même force de vérité dans leur périmètre.
--- title: Illustration des comptes locaux --- flowchart LR laptop["Client"] subgraph srv1 ["Serveur 1"] direction LR proc1[/"Processus 1"/] db1[("Base locale 1")] end subgraph srv2 ["Serveur 2"] direction LR proc2[/"Processus 2"/] db2[("Base locale 2")] end subgraph srv3 ["Serveur 3"] direction LR proc3[/"Processus 3"/] db3[("Base locale 3")] end laptop --> srv1 & srv2 & srv3 proc1 --> db1 proc2 --> db2 proc3 --> db3
La portée d’une identité peut être plus large et une identité peut être connue de plusieurs membres d’un système d’information ; on parle alors d’une identité centralisée.
Un référentiel d’identités central contient les identités d’un ensemble d’acteurs.
L’intérêt d’un tel référentiel devient évident à mesure qu’un système d’information s’agrandit ; gérer manuellement des identités locales sur de nombreux systèmes peut mener à des incohérences, et des oublis. En rassemblant les informations dans un référentiel central, il n’y alors qu’une seule source de vérité, faisant autorité pour l’ensemble du système d’information concerné. Il convient également de noter qu’il peut exister des copies de ces informations conservées en local sur les différents systèmes assujettis à ce référentiel d’identité. Ces copies ne font pas autorité, et il convient de surveiller leur cohérence avec la source de vérité et de les invalider ou les mettre à jour, le cas échéant.
Les copies sont souvent nécessaires à des fins de performance et de résilience. En effet, centraliser les identités présente des défis techniques notamment en matière de disponibilité ; une panne du référentiel central peut être de nature à stopper net l’ensemble des activités d’un système d’information.
Parmi les protocoles fréquemment utilisés pour la centralisation des identités, il est possible de citer LDAP2.
--- title: Illustration d'un annuaire centralisé --- flowchart LR laptop["Client"] subgraph srv1 ["Serveur 1"] direction TB proc1[/"Processus 1"/] dbs1[("Copie locale")] end subgraph srv2 ["Serveur 2"] direction TB proc2[/"Processus 2"/] dbs2[("Copie locale")] end subgraph srv3 ["Serveur 3"] direction TB proc3[/"Processus 3"/] dbs3[("Copie locale")] end subgraph ref ["Référentiel d'identité"] ldapsrv[/"Serveur LDAP"/] db[("Base d'identités")] end laptop --> srv1 & srv2 & srv3 srv1 & srv2 & srv3 --"LDAP"--> ref proc1 --> dbs1 proc2--> dbs2 proc3 --> dbs3 ldapsrv --> db
Un référentiel d’identités peut être amené à voir sa taille grandir, que ce soit de manière organique ou lors d’acquisitions de sociétés. Dans ce dernier cas, en particulier, il existe alors plusieurs référentiels d’identités concurrents, qu’il pourrait être intéressant de fusionner. Cette opération est sensible, et difficile.
Il existe des alternatives à la fusion ; l’établissement d’une forêt3 ou la mise en place d’un annuaire virtuel (Virtual Directory Service (VDS))4.
Une forêt est constituée d’un ensemble de référentiels d’identités indépendants entre lesquels il existe une relation de confiance. Ainsi, par transitivité de la confiance, les membres d’un référentiel d’identité accordent leur confiance aux identités gérées par un autre référentiel d’identité. Ce genre de schéma est très répandu dans les infrastructures Active Directory.
Les services d’annuaires virtuels jouent le rôle de serveurs mandataires pour l’accès à plusieurs référentiels d’identité. Ces derniers apparaissent alors comme “fusionnés” aux yeux des utilisateurs de service, alors qu’ils continuent d’être gérés individuellement.
--- title: Illustration d'annuaires répartis (forest) --- flowchart LR laptop["Client"] subgraph srv1 ["Serveur 1"] direction TB proc1[/"Processus 1"/] dbs1[("Copie locale")] end subgraph srv2 ["Serveur 2"] direction TB proc2[/"Processus 2"/] dbs2[("Copie locale")] end subgraph refnet ["Référentiel d'identité #quot;example.net#quot;"] direction TB ldapsrv[/"Serveur LDAP"/] db[("Base d'identités")] end subgraph refcom ["Référentiel d'identité #quot;example.com#quot;"] direction TB ldapsrv2[/"Serveur LDAP"/] db2[("Base d'identités")] end laptop --> srv1 & srv2 srv1 & srv2 --"LDAP"--> refcom proc1 --> dbs1 proc2 --> dbs2 ldapsrv --> db srv1 & srv2 --"LDAP"--> refnet ldapsrv2 --> db2
--- title: Illustration d'annuaires répartis (VDS) --- flowchart LR laptop["Client"] subgraph srv1 ["Serveur 1"] proc1[/"Processus 1"/] dbs1[("Copie locale")] end subgraph srv2 ["Serveur 2"] proc2[/"Processus 2"/] dbs2[("Copie locale")] end subgraph srv3 ["Serveur 3"] proc3[/"Processus 3"/] dbs3[("Copie locale")] end subgraph vds ["Virtual Directory Service"] direction TB vdss[/"Serveur VDS"/] dbss[("Copie locale")] end subgraph refnet ["Référentiel d'identité #quot;example.net#quot;"] ldapsrv[/"Serveur LDAP"/] db[("Base d'identités")] end subgraph refcom ["Référentiel d'identité #quot;example.com#quot;"] ldapsrv2[/"Serveur LDAP"/] db2[("Base d'identités")] end laptop --> srv1 & srv2 & srv3 proc1 --> dbs1 proc2 --> dbs2 proc3 --> dbs3 srv1 & srv2 & srv3 --"LDAP"--> vds vds --"LDAP"--> refcom & refnet vdss --> dbss ldapsrv --> db ldapsrv2 --> db2
Les référentiels d’identités répartis ont du sens lorsque l’ensemble des référentiels d’identités sont sous le contrôle d’entités juridiques ayant un rapport de confiance ou ayant la volonté d’apparaitre sous une même bannière. La confiance et l’unification s’effectuent par les gestionnaires des référentiels d’identités ; le consommateur de ces référentiels n’a aucun pouvoir de décision.
Il existe cependant une alternative dans le cas où ce genre de centralisation ou de répartition n’est pas possible ou souhaitable : l’utilisation de référentiels d’identités décentralisés. On parle alors d’identités fédérées.
Avec des référentiels d’identités décentralisés, chaque référentiel est géré par ses gestionnaires selon des politiques qui leur sont propres. C’est, en revanche, les responsables des systèmes d’information ayant besoin de connaitre l’identité de leurs utilisateurs et utilisatrices qui choisissent à quels fournisseurs de référentiels d’identités décentralisés ils font confiance ! Si l’identité d’un utilisateur ou d’une utilisatrice n’est pas gérée par un fournisseur de référentiels d’identité accrédité par les responsables d’un système d’information, il ou elle ne pourra pas se faire connaitre de ce système d’information.
Concernant la disponibilité, la plupart des services consommant des identités fédérées maintiennent en local une base de données avec des attributs supplémentaires spécifiques à leurs besoins métier. En revanche, si un fournisseur de référentiel d’identités est indisponible, les utilisateurs et les utilisatrices de ce fournisseur ne pourront plus se connecter à aucun service.
Les référentiels d’identités décentralisés sont devenus très populaires sur Internet, et de nombreux sites proposent ainsi de s’enregistrer ou de s’identifier à l’aide d’une identité fédérée. Ironiquement, cependant, peu de référentiels d’identités sont accrédités par les sites web, et les identités décentralisées reconnues se limitent souvent à celles gérées par quelques acteurs clés : Google, Facebook, Twitter, ou spécifiquement en France, France Connect.
L’interrogation de ces référentiels se fait à l’aide de protocoles plus ou moins standards. Parmi les plus répandus, on peut notamment citer OpenID Connect5 et SAML6.
--- title: Illustration d'annuaires décentralisés --- flowchart LR laptop["Client"] subgraph srv [Serveur] direction TB proc[/"Processus"/] dbs[("Base locale")] end subgraph refnet ["Référentiel d'identité #quot;example.net#quot;"] direction TB oidcsrv1[/"Serveur OpenID Connect"/] db1[("Base d'identités")] end subgraph refcom ["Référentiel d'identité #quot;example.com#quot;"] direction TB samlsrv1[/"Serveur SAML"/] db2[("Base d'identités")] end subgraph reforg ["Référentiel d'identité #quot;example.org#quot;"] direction TB oidcsrv2[/"Serveur OpenID Connect"/] db3[("Base d'identités")] end laptop --"Protocole OIDC/SAML"--> srv srv --"Accrédite"--> refnet srv --"Accrédite"--> refcom srv --"`N'accrédite *PAS*`"--> reforg; proc --> dbs laptop <-."Protocole OIDC".-> refnet laptop <-."Protocole SAML".-> refcom oidcsrv1 --> db1 samlsrv1 --> db2 oidcsrv2 --> db3 linkStyle 1,2 color:red;
Le référentiel SecNumCloud78 prévoit que les comptes d’administration d’un prestataire de cloud qualifié soient gérés “à l’aide d’outils et d’annuaires distincts de ceux utilisés pour la gestion des comptes utilisateurs placés sous la responsabilité du commanditaire (c’est-à-dire de ses clients)”.
Exigée pour les prestataires de cloud qualifiés, cette séparation des référentiels d’identités afin d’en dédier un pour les comptes d’administration du système d’information semble une bonne pratique de sécurité à adopter en général. Elle permet, en effet, de limiter la surface d’attaque des services manipulant notamment les clés cryptographiques utilisées pour l’administration (clés TLS, clés de signature des “jetons d’accès”, etc.).
L’authentification est un sujet complexe, que ce cours va aborder sous de nombreux angles :
L’authentification est un sujet traité à la fois par les juridictions nationales et internationales. Un défaut de conformité à ces dispositions peut entrainer des sanctions parfois sévères.
La Commission Nationale Information et Libertés (CNIL) a à plusieurs reprises sanctionné des sociétés mettant en place des mécanismes d’authentification trop faibles9, des politiques de sécurité entourant les moyens d’authentifications insuffisantes10, ou des mécanismes de stockage des éléments authentifiants trop faibles, mal déployés ou mal composés11.
Parmi les textes juridiques encadrant l’authentification, on peut notamment évoquer le règlement européen “Electronic Identification, Authentication and Trust Services” (eiDAS)12 et la “directive révisée sur les services de paiement” (DSP2)13.
En France, la directive DSP2 a été transposée notamment dans les articles L133-414 et L133-4415 du code monétaire et financier.
Pour le règlement eiDAS, des spécifications techniques viennent compléter les textes juridiques, notamment à des fins d’interopérabilité16. Des précisions techniques sont également apportées sur les contraintes pour satisfaire les différents niveaux de garantie définis par le règlement17. Une ordonnance18 donne le pouvoir à l’Agence Nationale de la Sécurité des Systèmes d’Information (ANSSI)19 de certifier des moyens d’authentification permettant de satisfaire ces niveaux de garantie. De plus amples informations sur le règlement eiDAS peuvent être trouvées sur le site de l’ANSSI20.
Nous reviendrons sur le contenu de ces textes au fur et à mesure que le cours abordera les notions qui y sont renseignées.
Outre les textes à valeurs juridiques, en France, l’ANSSI a publié divers référentiels et guides :
Le respect des règles et “recommandations” listées dans ces documents est requis pour l’obtention d’un certain nombre de qualifications de l’ANSSI, notamment SecNumCloud7.
Le règlement d’exécution (UE) 2015/150217 définit trois types de facteurs d’authentification.
a) “facteur d’authentification basé sur la possession”, un facteur d’authentification dont il revient au sujet de démontrer la possession;
b) “facteur d’authentification basé sur la connaissance”, un facteur d’authentification dont il revient au sujet de démontrer la connaissance;
c) “facteur d’authentification inhérent”, un facteur d’authentification qui est basé sur un attribut physique d’une personne physique, et dont il revient au sujet de démontrer qu’il possède cet attribut physique.
Cette définition est également présente dans le code monétaire et financier, ainsi que dans le RGS (à une subtilité prête ; voir le chapitre concernant la force de l’authentification).
D’après le guide de l’ANSSI “Recommandations relatives à l’authentification multifacteur et aux mots de passe” :
Un facteur de possession est un moyen de stocker des secrets non mémorisables par un humain (et n’ayant pas vocation à être mémorisés par un humain). Il s’agit typiquement des clés cryptographiques qui permettent de réaliser des opérations de chiffrement, de signature ou d’authentification.
Le même guide spécifie également :
Un facteur de possession doit être un équipement attribué à un unique utilisateur. Afin de garantir la sécurité apportée par ce facteur, il est essentiel que des moyens de protection et de détection contre les tentatives de reproduction ou de falsification du facteur soient mis en place. Un facteur de possession peut être une carte à puce contenant une clé privée, une carte SIM d’un téléphone mobile comportant des données d’identification, ou un dispositif permettant de générer des codes à usage unique (OTP).
Les facteurs d’authentification basés sur la connaissance reposent sur le fait que l’acteur connaisse un secret. En général, il s’agit d’un mot de passe, d’une phrase de passe, ou d’un code PIN (Personal Identification Number).
Les jetons d’authentification (authentication token ou bearer token) sont un cas intéressant lorsqu’on parle d’authentification multifacteurs. En effet, ces derniers sont soit des valeurs aléatoires assimilables à des clés cryptographiques symétriques, soit des informations structurées et signées et encodées sous la forme d’une chaine de caractères (par exemple en base64). La simple preuve de la connaissance d’un tel jeton est suffisante pour prouver son identité ; cela laisserait donc entendre qu’il s’agisse d’un facteur d’authentification basé sur la connaissance. Pourtant, il s’agit d’un secret non mémorisable par un humain, ce qui entrerait aussi dans certaines des définitions d’un facteur d’authentification basé sur la possession.
L’authentification par des facteurs inhérents est une question épineuse en France. En effet, l’ANSSI a longtemps été une pourfendeuse de la biométrie, indiquant que les facteurs inhérents sont au mieux un facteur d’identification et non d’authentification, ou dans le pire des cas une méthode de déverrouillage pour un autre facteur d’authentification. Cette position a dû être partiellement révisée par la contrainte européenne, au travers du règlement eiDAS et la directive DSP2.
Cette méfiance vis-à-vis de la biométrie n’est pourtant pas sans justification.
La vérification des facteurs inhérents s’effectue de manière probabiliste ; contrairement à la vérification des mots de passe ou des signatures cryptographiques, l’acquisition des données nécessaires à ce type de vérification n’est pas “parfaite”, et les algorithmes sont paramétrés avec des taux de faux positifs (validation d’une personne non autorisée) et de faux négatifs (refus d’une personne autorisée). Suivant le paramétrage, l’utilisateur fait alors face soit à un risque en confidentialité et en intégrité, soit à un risque en disponibilité. Ces paramétrages doivent d’ailleurs tenir compte qu’au cours du temps, certaines caractéristiques physiques changent ou s’estompent.
Ensuite, les facteurs inhérents ne sont pas renouvelables à l’infini ; si la révocation d’un moyen est possible, son remplacement ne l’est pas forcément.
Également, le risque de réutilisation d’une même caractéristique physique pour l’authentification auprès de plusieurs systèmes d’information peut comporter des risques de compromission croisée : un système d’information compromis pourrait permettre d’en compromettre un autre, à la manière d’une attaque dite de “credential stuffing”23. Cette attaque ne se limite cependant pas aux exfiltrations de données biométriques depuis des bases de données compromises ; par le passé, des chercheurs en sécurité ont réussi à extraire des données biométriques à partir de simples photos24.
La notion de facteurs d’authentification n’a réellement de sens que pour les utilisateurs. Par définition, un processus ne peut posséder un équipement ou mettre en œuvre un attribut physique.
Pourtant, l’exigence 9.6, alinéa f du référentiel SecNumCloud dispose que :
Le prestataire doit mettre en place un système d’authentification multifacteur fort pour l’accès :
- aux interfaces d’administration utilisées par le prestataire ;
- aux interfaces d’administration dédiées aux commanditaires.
Avec une lecture littérale, il semblerait donc impossible d’authentifier des processus autonomes (par exemple, les tâches planifiées ou les traitements de chaines d’intégration ou de déploiement continu (CI/CD)) pour l’administration d’un cloud qualifié SecNumCloud. Fort heureusement, les auditeurs SecNumCloud ne suivent pas à la lettre cette exigence mal écrite, et les prestataires de Cloud qualifiés proposent pour la plupart des interfaces d’administration programmables (API) sans avoir recours à une authentification multifacteur.
Il convient cependant de noter que strictement parlant, il pourrait être considéré qu’un processus puisse mettre en œuvre un facteur d’authentification basé sur la possession à l’aide d’équipements de sécurité particuliers : les Trusted Platform Module (TPM)25, les Hardware Security Module (HSM)26, et les Key Management Services (KMS)27. Ces équipements permettent la manipulation ou l’exercice de secrets sans en permettre l’extraction, la copie ou la falsification.
Le règlement eiDAS définit trois niveaux de garantie : faible, substantiel et élevé.
À chacun de ces niveaux de garantie sont associées des contraintes particulières. Parmi ces dernières, on peut notamment citer le nombre de facteurs d’authentification requis. Ainsi, le niveau faible ne requiert l’usage que d’un seul facteur, tandis que le niveau substantiel requiert au moins deux facteurs de nature différente.
La directive européenne DSP2 transposée dans le code monétaire et financier définit l’authentification forte comme étant :
[…] une authentification reposant sur l’utilisation de deux éléments ou plus appartenant aux catégories “connaissance” (quelque chose que seul l’utilisateur connait), “possession” (quelque chose que seul l’utilisateur possède) et “inhérence” (quelque chose que l’utilisateur est) et indépendants en ce sens que la compromission de l’un ne remet pas en question la fiabilité des autres, et qui est conçue de manière à protéger la confidentialité des données d’authentification ;
Cette définition de l’article L133-44 du code monétaire et financier vient en contradiction avec la définition de l’authentification forte que l’ANSSI emploie parfois. En effet, la définition de l’authentification forte dans le RGS est (presque) conforme à la définition du droit français:
Cette recommandation est en cohérence avec la notion traditionnelle « d’authentification forte », qui préconise de combiner deux mécanismes parmi ce que l’on sait, ce que l’on a, ce que l’on est ou ce que l’on sait faire.
On notera au passage que le RGS évoque “ce que l’on sait faire” qui est un facteur qui n’est ni reconnu par le règlement eiDAS, ni le code monétaire et financier.
En revanche, dans son guide “Recommandations relatives à l’authentification multifacteur et aux mots de passe” en version 2.0, le chapitre 2.5 distingue “authentification forte” et “authentification multifacteur”, en précisant :
En langue française, l’authentification multifacteur est souvent confondue avec l’appellation authentification forte (ou robuste), ce qui laisserait entendre qu’une authentification multifacteur est nécessairement plus robuste qu’une authentification avec un unique facteur.
[…]
Afin d’être considérée comme forte, une authentification doit reposer sur un protocole cryptographique permettant de résister à certaines attaques comme :
- l’écoute clandestine (eavesdroppping en anglais), qui consiste pour un attaquant à passivement écouter le canal de communication entre le prouveur et le vérifieur ;
- les attaques par rejeu, qui consistent pour un attaquant à récupérer des informations d’authentification (comme un mot de passe ou son empreinte) et à utiliser ces informations pour les rejouer afin d’usurper l’identité de la cible (l’attaque pass-the-hash [21] en est un exemple) ;
- les attaques de l’homme-du-milieu, qui consistent pour un attaquant à intercepter et modifier les communications se déroulant entre le prouveur et le vérifieur lors de l’authentification sans être détecté ;
- la non-forgeabilité : l’observation par un attaquant de plusieurs échanges d’authentification d’un prouveur ne doit pas lui permettre d’usurper son identité dans un nouvel échange d’authentification.
En outre, l’expression “authentification forte” est de plus en plus galvaudée par le marketing.
Il convient donc de toujours s’assurer de la définition de l’authentification forte qu’un interlocuteur ou une interlocutrice utilise.
Cette section du cours n’a pas vocation à être exhaustive. La liste qui suit n’est même pas forcément représentative des mécanismes les plus fréquemment utilisés. Elle permet cependant de couvrir un large éventail de techniques afin d’apporter une culture générale sur le sujet.
Dans cette section, on utilisera le terme de prouveur pour désigner celui qui tente de prouver son identité ; c’est-à-dire de s’authentifier. Le terme vérificateur désigne celui qui vérifie les preuves d’identité. On peut penser de prime abord que seul l’utilisateur tente de prouver son identité auprès d’un serveur pour accéder à son compte. La réalité est que presque toujours, le serveur prouve également son identité auprès du logiciel mis en œuvre par l’utilisateur ou l’utilisatrice. En conséquence, il serait incorrect de considérer que prouveur et utilisateurs sont synonymes dans le chapitre qui suit.
La méthode la plus universelle pour prouver son identité est de divulguer un secret au vérificateur. Ce dernier peut alors comparer ce secret à celui attendu pour cet acteur. S’ils correspondent, alors la preuve est faite. C’est le cas typique de l’utilisateur qui envoie son mot de passe tel quel à un serveur. C’est également le cas pour les codes temporels (TOTP), les codes Transaction Authentification Number (TAN) (par exemple, des codes reçus par email ou par SMS et à reproduire auprès du vérificateur), les codes PIN, les jetons d’authentification, etc. C’est également le cas des “identifiants de session”, comme les “cookies de session”, qui ne sont ni plus ni moins que des jetons d’authentification présentés à chacune des requêtes.
Ce mécanisme d’authentification présente de nombreux défauts, et a pour seul avantage d’être extrêmement simple à implémenter, à tout le moins du côté du prouveur. Côté vérificateur, les choses sont plus complexe : il s’agit de stocker de manière sécurisée le matériel nécessaire à la vérification de l’identité. Ce stockage sécurisé est l’objet d’un chapitre ultérieur.
Outre la nécessité d’un stockage sécurisé, ce mécanisme d’authentification nécessite que le secret exige sur un canal de communication assurant la confidentialité des données. Sans cela, un attaquant ou une attaquante n’aurait qu’à écouter passivement le réseau pour apprendre le secret. En outre, tous les logiciels manipulant le secret en clair et dans sa forme originale, tel que connu du prouveur, devraient mettre en place des mesures de sécurité afin de limiter les risques de divulgation de ce secret en cas de compromission logicielle : nettoyer la mémoire, mettre en place des pages de garde (page guards), isoler les traitements des secrets dans des processus séparés. En pratique, cela n’est presque jamais fait. C’est ainsi que des vulnérabilités comme Heartbleed28, qui avait permis de faire des lectures arbitraires dans la mémoire des processus utilisant OpenSSL pour sécuriser les communications, ont permis de récupérer les mots de passe non protégés directement en mémoire. Tous les secrets ainsi exfiltrés étaient directement utilisables pour se connecter aux comptes associés.
Finalement, ce mécanisme d’authentification ne présente aucune protection contre le rejeu. Ainsi, si le canal de communication est intercepté ou si l’utilisateur ou l’utilisatrice est victime d’une attaque par hameçonnage (phishing), et qu’il ou elle saisit son mot de passe sur le site frauduleux, alors l’attaquant ou l’attaquante apprendra le moyen de preuve et pourra le mettre en œuvre pour accéder au compte associé. Il conviendra néanmoins de nuancer l’impact de la vulnérabilité aux attaques par rejeu avec la durée de vie du secret divulgué : certains sont à usage unique ou ont une faible durée de validité (TOTP, TAN, etc.), tandis que d’autres ont des durées de vie beaucoup plus longues (par exemple, les mots de passe).
--- title: Authentification par divulgation d'un mot de passe --- sequenceDiagram autonumber actor peggy as Peggy box actor victor as Victor participant db as Base de données end peggy ->> victor:"Je m'appelle Peggy. Mon mot de passe est #quot;Bonjour1!#quot;." victor ->> victor:Calcule la dérivée du mot de passe reçu victor ->> db:"Quel est la dérivée du mot de pase de Peggy ?" db ->> victor:"Voici la dérivée du mot de passe de Peggy" victor ->> victor:Compare les deux dérivées alt Mot de passe valide victor ->> peggy:"Bonjour Peggy" else Mot de passe invalide victor ->> peggy:"Je ne crois pas, non" end
Les mécanismes d’authentification reposant sur des défis sont des procédés interactifs : un dialogue se met en place entre le vérificateur et le prouveur. Ce dialogue permet de s’accorder sur une valeur aléatoire, parfois appelée nonce. Cet accord peut être unilatéral : le vérificateur décide arbitrairement de cette valeur. Ensuite le prouveur effectue une opération cryptographique sur cette valeur aléatoire et envoie le résultat au vérificateur. Ce dernier vérifie alors la preuve à l’aide d’un élément en sa possession et qui est associé à l’identité supposée du prouveur.
Il existe de nombreux protocoles reposant sur les défis ; certains ont de très bonnes propriétés de sécurité ; d’autres sont catastrophiquement mauvais, et même pires que la preuve par divulgation !
La RFC 761629 décrit le mécanisme d’authentification HTTP Digest.
Le vérificateur génère un nonce et l’envoie au prouveur. Ce dernier utilise alors une fonction de hachage cryptographique sur la concaténation de l’identité à prouver, le mot de passe associé à cette identité, le nonce, le verbe HTTP et l’URI demandée. Le résultat de la fonction de hachage est envoyé au vérificateur. Ce dernier exécute la fonction de hachage de son côté avec les mêmes entrées. Si le résultat de la fonction de hachage appelée par le vérificateur est identique à celui transmis par le prouveur, alors la preuve est faite.
L’intérêt supposé de ce mécanisme d’authentification est que le mot de passe n’est à aucun moment transmis dans la requête HTTP. Celui-ci est protégé par la résistance de la fonction de hachage cryptographique à la découverte d’une préimage30.
Cet intérêt supposé est cependant assez peu pertinent étant donné que l’essentiel des communications HTTP est de nos jours transporté sur des canaux de communication chiffrés (par TLS ou HTTP/3 qui intègrent directement le chiffrement).
Un intérêt notable de ce mécanisme d’authentification est l’inclusion d’un nonce. Ce dernier permet de contrer les attaques par rejeu ; en effet, même en cas d’interception d’une preuve, il n’est pas possible de l’utiliser pour réaliser des tentatives d’authentification futures par simple rejeu.
En revanche, ce mécanisme d’authentification requiert que le vérificateur connaisse le mot de passe de l’utilisateur31 et qu’il le stocke tel quel, ou sous un format réversible. En conséquence, en cas de fuite de la base de données du vérificateur, un attaquant pourrait immédiatement utiliser les valeurs récupérées pour usurper l’identité de tous les acteurs auprès de ce vérificateur. Cet inconvénient majeur disqualifie totalement ce mécanisme d’authentification, qui ne doit jamais être employé.
Un autre problème de sécurité est que la divulgation de toute preuve à un attaquant ou une attaquante lui permet d’effectuer ensuite une recherche exhaustive hors-ligne sur le mot de passe qui a permis de générer cette preuve ; tous les autres éléments sont connus. La possibilité de recherche exhaustive hors-ligne sur des mots de passe est agravée par le fait que les fonctions de hachage spécifiées dans la RFC sont très insuffisantes ; ces considérations de sécurité sont identiques à celles discutées dans le chapitre sur le stockage des dérivées des mots de passe.
--- title: Authentification avec HTTP Digest (simplifiée) --- sequenceDiagram autonumber actor peggy as Peggy box actor victor as Victor participant db as Base de données end peggy ->> victor:"Je voudrais faire X sur l'adresse Y." victor ->> peggy:"Heu, t'es qui ? Voici un nonce." peggy ->> peggy: Calcule le condensat, avec son nom, son mot de passe, X, Y et le nonce peggy ->> victor:"Je m'appelle Peggy. Je voudrais faire X sur l'adresse Y. Voici le nonce et mon condensat." victor ->> db: "C'est quoi le mot de passe de Peggy ?" db ->> victor: "Le mot de passe de Peggy est #quot;Bonjour1!#quot;..." victor ->> victor:Calcule le condensat, avec le nom #quot;Peggy#quot;, le mot de passe de Peggy, X, Y et le nonce alt Les condensats correspondent victor ->> peggy:"Bonjour Peggy. Voici le résultat de X sur Y." else Les condensats ne correspondent pas victor ->> peggy:"Je ne crois pas, non" end
La signature électronique est une méthode d’authentification très courante. Elle est notamment employée par les protocoles SSH, TLS, et IPsec.
Le principe général est que le prouveur dispose d’une clé privée et le vérificateur dispose de la clé publique associée. Le prouveur effectue la signature électronique d’un nonce et le vérificateur n’a alors qu’à utiliser la clé publique pour en vérifier l’authenticité. Si elle est authentique, alors la preuve est faite.
Ce mécanisme d’authentification présente l’avantage de lever toute contrainte relative à la confidentialité du stockage par le vérificateur : seule une clé publique est stockée, dont la divulgation ne remet pas en cause la sécurité du mécanisme d’authentification. La contrainte d’intégrité du stockage de la clé publique peut elle-même être levée si la clé publique est inscrite dans un certificat, faisait partie d’une infrastructure de clés. Il faudra néanmoins assurer l’intégrité du certificat racine de l’infrastructure de clés.
Des précautions doivent cependant être prises, notamment pour éviter les attaques par rejeu. En effet, il est important que le prouveur s’assure que les nonces ne soient jamais réutilisés (en général ou au minimum par un même vérificateur). En effet, si un nonce était réutilisé, il ne serait plus nécessaire d’avoir accès à la clé privée permettant la signature ; il suffirait juste de rejouer la preuve correspondante qui aurait été générée la première fois que ce nonce avait été signé. Un attaquant ou une attaquante pourrait également hameçonner un prouveur dans le cadre d’une attaque par relais. Cette attaque consiste alors à présenter au prouveur le nonce choisi par le vérificateur, récupérer cette preuve et la jouer à son compte auprès du véritable vérificateur.
Pour contrer ces attaques par rejeu ou par relais, la plupart des implémentations font intervenir le prouveur dans le choix du nonce ; le prouveur est alors sûr qu’au moins sa propre contribution à l’établissement du nonce est réellement aléatoire et non rejouée.
Une autre contremesure aux attaques par relais est de s’assurer que le prouveur utilise une clé privée différente par vérificateur. Le prouveur peut utiliser, par exemple, le nom du site web consulté comme discriminant. Ainsi, en cas d’hameçonnage, le site web de l’attaquant ou de l’attaquante ne dispose pas de la même URL et, pour générer la signature, la clé privée utilisée est différente de la clé qui serait utilisée pour le vérificateur légitime. En conséquence, la preuve interceptée par l’attaquant ou l’attaquante n’est pas valide auprès du véritable vérificateur ! Cette parade peut être utilisée en plus de la précédente ; leur combinaison est utilisée par les protocoles WebAuthn, U2F et FIDO2, détaillés ultérieurement dans ce cours.
--- title: Authentification d'un serveur TLS avec confidentialité persistente (simplifiée) --- sequenceDiagram autonumber actor peggy as Peggy (Serveur TLS) actor victor as Victor (Client TLS) victor ->> victor:Tire un nonce victor ->> victor:Tire une bi-clé temporaire (DHE) victor ->> peggy:"Je voudrais consulter https://broken-by-design.fr. Voici un nonce et une clé publique temporaire" peggy ->> peggy:Tire un nonce peggy ->> peggy:Tire une bi-clé temporaire (DHE) peggy ->> peggy:Prépare le message "Voici un autre nonce" peggy ->> peggy:Prépare le message "Voici un certificat pour broken-by-design.fr" peggy ->> peggy:Prépare le message "Voici une autre clé publique temporaire" peggy ->> peggy:Calcule un condensat cryptographique de l'ensemble des messages échangés et préparés peggy ->> peggy:Signe avec sa clé privée le condensat cryptographique peggy ->> victor:"Voici un autre nonce" peggy ->> victor:"Voici un certificat pour broken-by-design.fr" peggy ->> victor:"Voici une autre clé publique temporaire" peggy ->> victor:"Voici la signature des messages précédents" victor ->> victor:Vérifie l'authenticité du certificat victor ->> victor:Calcule le condensat cryptographique de l'ensemble des messages reçus (sauf la signature). victor ->> victor:Vérifie la signature cryptographique reçue avec la clé publique du certificat alt La signature est valide par Calcul des clés par Peggy peggy ->> victor:"Top ! À partir de maintenant, échangeons de manière sécurisée." peggy ->> peggy:Calcule le PMS et les autres clés and Calcul des clés par Victor victor ->> peggy:"Top ! À partir de maintenant, échangeons de manière sécurisée." victor ->> victor:Calcule le PMS et les autres clés end victor -> peggy:"#10216;illisible#10217; (vérification de l'intégrité des échanges précédents)" victor -> peggy:"#10216;illisible#10217; (échanges métier)" else La signature est invalide victor ->> peggy:"Je ne crois pas, non" end
La preuve par déchiffrement repose sur la capacité du prouveur à démontrer la connaissance d’un secret arbitraire qui lui a été transmis sous une forme chiffrée par le vérificateur.
Pour déchiffrer ce secret arbitraire, le prouveur doit disposer d’une clé symétrique ou d’une clé privée. La clé symétrique peut être issue d’un calcul, comme le résultat d’une fonction de dérivation de mot de passe (voir chapitre sur le stockage des éléments authentifiants pour en apprendre plus sur ces fonctions).
En déchiffrant le secret arbitraire envoyé par le vérificateur, le prouveur démontre qu’il connait la clé de déchiffrement et donc qu’il est celui qu’il prétend être. Cela est pourtant insuffisant pour convaincre le vérificateur, puisque ce dernier ne sait encore rien du résultat de ce déchiffrement. Une nouvelle opération cryptographique est donc nécessaire : le prouveur doit exercer ce secret arbitraire dans une opération cryptographique et envoyer le résultat de cette dernière au vérificateur. Le vérificateur pourra alors vérifier que l’opération cryptographique a bien mis en œuvre le secret qu’il avait envoyé au prouveur.
Les implémentations de cette preuve varient beaucoup. Elle est employée par le protocole Kerberos ou par certaines suites cryptographiques de TLS.
Avec les suites cryptographiques de TLS ne mettant pas en œuvre la confidentialité persistante (perfect forward secrecy (PFS)), le vérificateur (le client TLS) va envoyer au prouveur (le serveur TLS) un secret chiffré avec la clé publique contenue dans le certificat du serveur TLS. Si le serveur TLS est bien en possession de la clé privée associée à la clé publique contenue dans le certificat, il pourra déchiffrer ce secret. Ce secret, appelé “pre-master secret (PMS)” est utilisé ensuite par le vérificateur et le prouveur pour calculer les clés cryptographiques qui seront utilisées pour sécuriser l’ensemble de la communication TLS. Si le prouveur n’a pas été en mesure de déchiffrer le PMS, il ne sera pas en mesure de lire, ni de répondre aux messages chiffrés envoyés par le vérificateur. Si en revanche, il est en mesure de le faire, alors implicitement, il aura prouvé qu’il était en possession de la clé privée et la preuve d’identité sera faite.
--- title: Authentification TLS sans confidentialité persistente (simplifiée) --- sequenceDiagram autonumber actor peggy as Peggy (Serveur TLS) actor victor as Victor (Client TLS) victor ->> victor:Tire un nonce victor ->> peggy:"Je voudrais consulter https://broken-by-design.fr. Voici un nonce." peggy ->> peggy:Tire un autre nonce peggy ->> victor:"Voici un autre nonce" peggy ->> victor:"Voici un certificat pour broken-by-design.fr" victor ->> victor:Vérifie l'authenticité du certificat reçu victor ->> victor:Tire le PMS victor ->> victor:Chiffre le PMS avec la clé publique du certificat victor ->> peggy:"Voici le PMS chiffré" par Peggy indique chiffrer ses communications peggy ->> victor:"Top ! À partir de maintenant, échangeons de manière sécurisée." and Victor indique chiffrer ses communications victor ->> peggy:"Top ! À partir de maintenant, échangeons de manière sécurisée." end alt Peggy ne connait pas la clé privée peggy --x victor:Peggy ne dispose pas des clés pour chiffrer un message pour Victor else Peggy connait la clé privée peggy ->> peggy:Déchiffre le PMS avec sa clé privée par Calcul des clés par Peggy peggy ->> peggy:Calcule les autres clés à partir du PMS and Calcul des clés par Victor victor ->> victor:Calcule les autres clés à partir du PMS end alt Peggy envoie en premier à Victor un message de vérification des échanges peggy ->> peggy:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici peggy ->> peggy:Protège le condensat en intégrité et confidentialité avec les clés calculées peggy ->> victor:"[Chiffré] Voici le condensat de nos échanges" victor ->> victor:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici sauf le dernier reçu victor ->> victor:Compare le condensat reçu à celui qu'il a calculé alt Les condensats ne correspondent pas victor ->> peggy: "Je ne crois pas, non." else Les condensats correspondent victor ->> victor:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici victor ->> victor:Protège le condensat en intégrité et confidentialité avec les clés calculées victor ->> peggy:"[Chiffré] Voici le condensat de nos échanges" peggy ->> peggy:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici sauf le dernier reçu peggy ->> peggy:Compare le condensat reçu à celui qu'il a calculé alt Les condensats correspondent peggy -> victor:"[Chiffré] Données métier" else Les condensats ne correspondent pas peggy ->> victor: "Je ne crois pas, non." end end else Victor envoie en premier à Peggy un message de vérification des échanges victor ->> victor:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici victor ->> victor:Protège le condensat en intégrité et confidentialité avec les clés calculées victor ->> peggy:"[Chiffré] Voici le condensat de nos échanges" peggy ->> peggy:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici sauf le dernier reçu peggy ->> peggy:Compare le condensat reçu à celui qu'il a calculé alt Les condensats ne correspondent pas peggy ->> victor: "Je ne crois pas, non." else Les condensats correspondent peggy ->> peggy:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici peggy ->> peggy:Protège le condensat en intégrité et confidentialité avec les clés calculées peggy ->> victor:"[Chiffré] Voici le condensat de nos échanges" victor ->> victor:Calcule un condensat cryptographique de tous les messages échangés jusqu'ici sauf le dernier reçu victor ->> victor:Compare le condensat reçu à celui qu'il a calculé alt Les condensats correspondent victor -> peggy:"[Chiffré] Données métier" else Les condensats ne correspondent pas victor ->> peggy: "Je ne crois pas, non." end end end end
Avec Kerberos, le mot de passe du prouveur est utilisé pour déchiffrer une clé symétrique envoyée par le serveur d’authentification (authentication server (AS)). Cette clé est ensuite utilisée par le prouveur pour chiffrer un message à destination du serveur d’émission de tickets (ticket granting service (TGS)). Ce serveur s’attend à ce que le message soit chiffré avec une clé particulière : celle envoyée chiffrée au prouveur par le serveur d’authentification. Ce mécanisme d’authentification est un peu plus complexe qu’expliqué plus haut, car le rôle de vérificateur est, en fait, endossé par deux acteurs distincts : le serveur d’authentification d’une part, et le serveur d’émission de tickets d’autre part.
--- title: Authentification Kerberos (simplifiée) --- sequenceDiagram autonumber actor peggy as Peggy (Client) box Serveur(s) actor trent as Trent (Serveur d'authentification) actor victor as Victor (Serveur d'émission de tickets) participant db as Base de données end peggy ->> trent:"Je suis Peggy.". trent ->> db:"C'est quoi la dérivée du mot de passe de Peggy ?" db ->> trent:"La dérivée du mot de passe de Peggy est..." trent ->> db:"C'est quoi la clé de Victor ?" db ->> trent:"La clé de Victor est..." trent ->> trent:Tire une clé A trent ->> peggy:"[Chiffré avec la dérivée du mot de passe de Peggy] Voici la clé A. trent ->> peggy:"[Chiffré avec la clé de Victor] Elle dit s'appeler Peggy. Ce message est valide M secondes/minutes/heures. Voici la clé A." peggy ->> peggy:Dérive son mot de passe peggy ->> peggy:Déchiffre la clé A avec la dérivée de son mot de passe peggy ->> victor:"Trent m'a donné ce message pour toi." victor ->> victor:Déchiffre le message de Trent avec sa propre clé victor ->> victor:Vérifie la période de validité de ces informations alt La période de validité est expirée victor ->> peggy:"Je ne crois pas, non." else La période de validité est en cours peggy ->> victor:"[Chiffré avec la clé A] "Je suis Peggy. Je veux accéder au serveur X." victor ->> victor:Déchiffre le message Peggy avec la clé A victor ->> victor:Vérifie que le nom Peggy figure bien dans les deux messages déchiffrés alt Peggy ne connait pas véritablement la clé A, car c'était le mauvais mot de passe. Son nom ne figure pas dans son message après déchiffrement. victor ->> peggy:"Je ne crois pas, non." else Peggy connait la clé A. Son nom figure bien dans le message qu'elle a chiffré. Note right of victor:Victor continue le protocole avec la partie "autorisation" end end
La preuve d’identité par déchiffrement est plus complexe à mettre en œuvre et ses assurances de sécurité sont plus faibles que d’autres types de preuves, notamment comme implémentée dans TLS 1.3. En conséquence, cette preuve est de moins en moins utilisée. Il s’agit d’un bel exemple du développement itératif et de l’amélioration continue des protocoles cryptographiques ; beaucoup de ceux conçus dans les années 90 sont désormais écartés au profit de constructions plus récentes et robustes.
Les mécanismes reposant sur la preuve par divulgation nulle de connaissance (ou sans apport de connaissance) sont assez divers. Le principe commun de tous ces mécanismes est que l’élément secret utilisé par le prouveur n’est à aucun moment divulgué au vérificateur. Ce dernier reçoit la preuve de la connaissance de ce secret, sans obtenir d’information sur le secret !
La divulgation nulle de connaissance semble souvent “magique”. Jean-Jacques Quisquater et Louis Guillou ont publié en 1989 un article de vulgarisation intitulé “Comment expliquer à vos enfants les protocoles sans apport de connaissance”, dont le récit est rapporté et traduit dans un article Wikipedia, et dont la lecture peut se révéler éclairante.32.
Une caractéristique intéressante de la preuve à divulgation nulle de connaissance telle qu’implémentée dans le protocole de Schnorr33, ou dans celui de Guillou-Quisquater34, est que le vérificateur peut être raisonnablement certain de la preuve35 qui lui est apportée par le prouveur, tout en étant parfaitement incapable de convaincre un tiers de la même chose, a posteriori. Cette propriété est particulièrement intéressante dans le cas d’applications préservant la vie privée et nécessitant d’authentifier un acteur tout en pouvant nier de manière plausible avoir des preuves que cette authentification ait eu lieu.
--- title: Illustration du protocole de Feige–Fiat–Shamir (simplifié) --- sequenceDiagram autonumber actor p as Peggy box actor v as Victor participant db as Base de données end p ->> v:"Je suis Peggy." v ->> db:"C'est quoi la clé publique de Peggy ?" db ->> v:"La clé publique de Peggy est..." v ->> p:"Convaincs moi." p ->> p: Se munit de sa clé privée S loop Jusqu'à ce que Victor soit convaincu ou que Peggy ne calcule pas correctement p ->> p:Tire une valeur aléatoire x, et calcule une fonction D(x) = X p ->> v:"Voici X" v ->> v:Tire à pile ou face v --> p:"Voici le résultat du tirage à pile ou face" p ->> p:Calcule la fonction F(S, x, pile ou face) = Y p ->> v:"Voici le résultat du calcul" v ->> v:Vérifie le calcul avec la clé publique de Peggy avec une fonction G(X, Y, clé publique de Peggy) alt Le calcul est correct v ->> v:Est un peu plus convaincu else Le calcul est incorrect v ->> p: "Je ne te crois pas. Fin de conversation." end end
Par proximité avec les protocoles à divulgation nulle de connaissance, il peut être fait mention également de ceux utilisant des fonctions pseudo-aléatoires oublieuses (oblivious pseudo-random functions (OPRF) ; il n’existe pas de traduction faisant autorité).
Les OPRF sont des fonctions impliquant deux parties qui contribuent aux entrées d’une fonction générant un nombre aléatoire. L’une des parties apprend la valeur de sortie de la fonction, sans avoir appris la contribution de l’autre partie ; et l’autre partie n’apprend rien. La RFC 949736 décrit une fonction de cette nature. Cette construction est utilisée dans deux protocoles d’authentification très différents : Privacy Pass37 et Opaque38.
Privacy Pass est un protocole d’authentification permettant de prouver non pas une identité individuelle, mais l’appartenance à un groupe d’individus, sans pouvoir distinguer l’individu. Il s’agit bien d’une authentification : un acteur prouve une identité (de groupe) à un vérificateur, qui, en cas de succès, le reconnait bien comme ayant cette identité (d’appartenance à ce groupe). On pourrait, par exemple, imaginer un service de vidéos à la demande payant, qui authentifierait un acteur sans être capable de tracer ce qu’il visionne ; tout ce qu’il saurait, c’est que l’acteur accèdant à la vidéo est à jour de son abonnement. La cryptographie impliquée est un peu avancée pour ce cours, mais le lecteur intéressé pourra en apprendre plus en consultant les documents du groupe de travail “Privacy Pass” de l’Internet Engineering Task Force (IETF).
Opaque, quant à lui, est un protocole d’authentification de la catégorie des Strong Asymmetric Password-based Authenticated Key Exchange (SaPAKE), et utilise donc un mot de passe pour effectuer l’authentification. Il utilise cependant une OPRF afin de permettre de prouver une identité spécifique sans divulguer d’information sur le mot de passe auprès du vérificateur ! L’OPRF est, en effet, utilisée pour calculer une valeur dérivée du mot de passe qui permet le déverrouillage d’un coffre-fort numérique contenant une clé privée. Cette clé privée est ensuite utilisée pour générer la signature d’un défi, comme dans le cas classique des protocoles à signature de défis. L’intérêt d’avoir utilisé une OPRF est que le vérificateur est impliqué dans chaque tentative de déverrouillage du coffre-fort, ce qui lui permet d’empêcher les attaques par recherche exhaustive et de “verrouiller” le compte associé à cette identité si le nombre d’échecs est trop important ! Une fonctionnalité bien utile qui devrait être implémentée par tous les fournisseurs de gestionnaires de mots de passe en ligne synchronisés dans le cloud… De son côté, Whatsapp a mis en œuvre Opaque pour ses sauvegardes chiffrées de bout-en-bout39.
--- title: Authentification avec le protocole Opaque (simplifiée) --- sequenceDiagram autonumber actor p as Peggy box actor v as Victor participant db as Base de données end p ->> p:Tire une valeur aléatoire R p ->> p:Calcule 1/R p ->> p:Dérive son mot de passe p ->> v:"Je suis Peggy." p ->> v:"[Chiffré avec R]La dérivée de mon mot de passe est..." v ->> p:"Voici ton coffre-fort." v ->> v: Se munit de sa clé S v ->> p:"[Chiffré avec S][Chiffré avec R]La dérivée de mon mot de passe est..." v ->> v: Tire un nonce v ->> p:"Voici un nonce" p --> p:Déchiffre le message reçu avec 1/R, ce qui donne "[Chiffré avec S]La dérivée de mon mot de passe est..." alt Peggy ne connait pas son mot de passe Note right of p:Utiliser "[Chiffré avec S]La dérivée de mon mot de passe est..." comme clé ne permet pas de déchiffrer le coffre-fort. "Peggy" ne peut continuer le protocole. else p ->> p:Utilise "[Chiffré avec S]La dérivée de mon mot de passe est..." comme clé pour déchiffrer le coffre-fort p ->> p:Utilise la clé privée contenue dans le coffre pour signer le nonce p ->> v:"Voici le nonce signé" v ->> db:"C'est quoi la clé publique de Peggy ?" db ->> v:"La clé publique de Peggy est..." v ->> v:Vérifie la signature du nonce avec la clé publique de Peggy alt La signature est valide v ->> p:"Bonjour Peggy!" else La signature est invalide v ->> p:"Je ne crois pas, non." end end
Pour effectuer l’authentification d’un acteur, le vérificateur a besoin d’avoir accès à une information permettant de vérifier la preuve d’identité. De la nature de la preuve dépend la nature de l’information à stocker côté vérificateur. Le cas le plus typique est celui du mot de passe, mais il en existe d’autres, comme les secrets permettant la génération des codes temporels (TOTP), des clés publiques ou des certificats.
Dans le cas où la preuve consiste en une signature numérique vérifiable avec la cryptographie à clé publique, tous les éléments stockés par le vérificateur sont publics par nature ; la seule protection requise est en intégrité, afin de prévenir un attaquant de remplacer les éléments de vérification par les siens. La confidentialité peut néanmoins être un sujet, en particulier si les clés sont réutilisées auprès de plusieurs vérificateurs (voir la section de ce cours dédiée à la réutilisation des moyens de preuve).
La cryptographie à clé secrète ou cryptographie symétrique effectue les opérations de vérification avec la même clé que celle qui a permis de créer la preuve. En conséquence, cette clé doit être stockée en clair, sous une forme réversible, ou dans un équipement de sécurité (par exemple, un TPM, un HSM, ou une carte à puce) permettant sa mise en œuvre sans risque d’extraction, copie ou falsification. Ce dernier cas est malheureusement trop rare.
Étant donné que la compromission en confidentialité du stockage du vérificateur permet ensuite l’usurpation de l’identité des acteurs, les protocoles utilisant de la cryptographie à clé secrète sont à éviter, en particulier s’il s’agit de l’unique facteur d’authentification.
C’est le cas notamment des protocoles utilisant les mécanismes de preuve de type challenge/response, comme le mode “digest” de HTTP, spécifié dans la RFC 761629. C’est également le cas du protocole TOTP, spécifié dans la RFC 623840.
Le stockage des mots de passe par le vérificateur est sans doute la problématique liée à l’authentification la plus connue, du fait de la quasi-omniprésence des mots de passe comme méthode d’authentification, des méthodes de stockage qui ont largement évolué à mesure que les techniques d’attaque se sont sophistiquées, et des sanctions de la CNIL qui ont été mises en avant sur ces sujets.
Si le mot de passe de l’utilisateur est stocké en clair par le vérificateur, alors la problématique est la même que lorsqu’est utilisé un protocole reposant sur de la cryptographie à clé secrète.
Une meilleure méthode consiste à stocker non pas le mot de passe lui-même, mais le résultat d’une fonction dite de dérivation au mot de passe. Ce résultat de la dérivée est parfois appelé “empreinte”. Parfois, la fonction de dérivation est appelée “fonction de hachage”, de manière abusive, du fait que nombre de ces dérivations sont faites à l’aide de fonctions de hachage cryptographiques. Il existe de très nombreuses fonctions de dérivation, comme nous le verrons plus loin, avec des niveaux de sécurité assez variables.
Finalement, la meilleure méthode reste encore de ne pas transmettre du tout le mot de passe au vérificateur, mais plutôt d’utiliser le mot de passe pour générer une preuve vérifiable ; cette preuve est alors l’unique élément transmis au vérificateur qui ignore tout du mot de passe de l’acteur ! C’est le cas avec le protocole OPAQUE présenté précédemment dans ce cours.
Concernant la dérivation des mots de passe, les principales attaques sont :
Pour ce qui est de la recherche exhaustive ou guidée, si le mot de passe est trop faible, la méthode de dérivation utilisée n’aura pas d’incidence sur la difficulté à retrouver le mot de passe. Même avec la meilleure fonction théoriquement possible, le mot de passe “password” sera cassé presque instantanément. Le guide ANSSI “Recommandations relatives à l’authentification multifacteur et aux mots de passe” indique qu’un mot de passe doit avoir une entropie allant de 65 bits à plus de 100 bits en fonction du niveau de risque associé au compte protégé par ce mot de passe. L’entropie est calculée avec le log_2 du nombre de combinaisons possibles d’un jeu de caractères sur une longueur donnée. Par exemple, si un mot de passe est uniquement numérique, et composé de 10 chiffres, alors l’entropie est de 10 puissance 10, et l’entropie est donc log_2(10^10), soit 33 bits.
De même, si l’acteur utilise le même mot de passe auprès de plusieurs vérificateurs, alors la sécurité du stockage de ce mot de passe est équivalente à la sécurité de la méthode de stockage la plus faible employée par l’un de ces vérificateurs. Si cette méthode de stockage est trop faible, alors le mot de passe peut être recouvré puis utilisé auprès d’un vérificateur ayant pourtant une bonne méthode de stockage ; c’est ce qu’on appelle le “bourrage” de mots de passe. Dans ce cas, peu importe la fonction de dérivation employée : le mot de passe peut être cassé en une seule tentative, puisque le mot de passe est en fait déjà connu.
Pour freiner la recherche exhaustive, il convient d’utiliser une fonction de dérivation qui soit raisonnablement couteuse à calculer. Plus la fonction est couteuse, plus il faudra de temps pour retrouver le mot de passe à partir de sa dérivée. Il y a cependant un arbitrage à faire, car pour chaque tentative de vérification d’un mot de passe, le vérificateur devra utiliser cette fonction couteuse également. S’il y a peu d’utilisateurs, comme c’est le cas pour une authentification locale sur un poste de travail, cela ne présente pas un gros problème, mais sur un site web avec des millions d’utilisateurs et d’utilisatrices, le cout peut rapidement devenir prohibitif.
Le précalcul est une attaque qui vise à précalculer un grand nombre de dérivées de mots de passe, et d’indexer efficacement le résultat de ces calculs. Cet index permet d’optimiser le temps nécessaire pour casser les mots de passe dont les dérivées auraient fuité. Plus besoin d’exécuter la fonction de dérivation pour chaque mot de passe à attaquer ! Il suffit de regarder si la dérivée est présente dans l’index, et si oui de regarder quel mot de passe lui correspond. Ces index sont appelés des tables arc-en-ciel (rainbow tables).
Pour contrer le précalcul, une donnée aléatoire spécifique à chaque compte de chaque système d’information doit être ajoutée au mot de passe en entrée de la fonction de dérivation. Cette donnée est parfois appelée “sel” ou “diversificateur”. Plus cette donnée contient d’entropie, plus le cout du précalcul devient élevé. Le guide ANSSI “Recommandations relatives à l’authentification multifacteur et aux mots de passe” préconise une donnée d’au moins 128 bits d’entropie !
Finalement, l’attaque par épluchage des mots de passe consiste à exploiter le fait que la fonction de dérivation soit en fait une composition de plusieurs fonctions de dérivation unitairement moins fortes que leur assemblage. L’exploitation consiste alors à attaquer chacune de ces fonctions individuellement ; si certaines sont trop faibles, alors l’attaquant peut accélérer d’autant sa recherche exhaustive. C’est par exemple ce qui a été reproché par la CNIL à Doctissimo, qui avait utilisé un assemblage MD5+bcrypt.
La fonction de dérivation de mots de passe à l’état de l’art est argon2id. Cette fonction dérive les mots de passe de telle façon que les calculs ne puissent être faits sur des cartes graphiques. Cette propriété est importante, car les recherches exhaustives ont longtemps été faites sur des cartes graphiques, disposant de processeurs capables d’effectuer de très grandes quantités de certains types de calcul, bien supérieures aux processeurs généralistes. Ensuite, argon2id peut consommer de grandes quantités de mémoire lors de la dérivation des mots de passe, ce qui permet d’accroitre encore le cout d’une recherche exhaustive. Finalement, argon2id met en œuvre un certain nombre de précautions pour éviter des attaques par canaux auxiliaires rendus possibles à cause des techniques permettant de faire consommer plus de mémoire : une protection sur la protection, en somme !
Il existe d’autres fonctions, moins efficaces que argon2id, qui peuvent être mentionnées. Par ordre décroissant de protection, il peut être cité : scrypt, bcrypt, PBKDF2. Toutes ces fonctions, comme argon2id, intègrent toutes par conception un diversificateur pour contrer les précalculs.
L’utilisation d’un même moyen permettant de prouver son identité n’est pas recommandée. Les conséquences sont cependant assez diverses en fonction du moyen.
La réutilisation d’un moyen dans le cadre d’un mécanisme d’authentification par divulgation a des conséquences catastrophiques si le canal de communication ou la sécurité logicielle du prouveur et du vérificateur sont insuffisamment protégés en confidentialité. En effet, l’attaquant ou l’attaquante pourra alors apprendre le secret et le réutiliser en l’état auprès d’un autre vérificateur.
La réutilisation de mots de passe pose également des difficultés relatives au stockage par le vérificateur. Le stockage du mot de passe lui-même, en clair ou sous un format réversible, signifie que l’attaquant ou l’attaquante ayant accès à ce stockage peut apprendre le mot de passe et le réutiliser tel quel auprès d’autres vérificateurs. Même si le stockage ne contient que des dérivées des mots de passe, le risque reste réel si l’entropie de ces mots de passe est trop faible. En effet, ils pourront être retrouvés par recherche exhaustive, avec les mêmes conséquences que s’ils avaient été stockés en clair.
Avec les mécanismes d’authentification utilisant la signature électronique, l’utilisation d’une même clé privée auprès de plusieurs vérificateurs présente également des risques.
D’une part, il arrive que des erreurs d’implémentation permettent à un vérificateur malveillant d’exploiter une vulnérabilité dans le code du prouveur, menant à la divulgation de la clé privée utilisée pour prouver son identité 4344.
D’autre part, un attaquant ou une attaquante ayant pu obtenir la liste des clés publiques associées à des identités auprès de divers vérificateurs pourrait relier les identités entre elles. Il ou elle lui serait alors possible de tracer et corréler les activités sur les systèmes d’information accessibles après authentification auprès de ces vérificateurs45.
Fort de toutes les connaissances évoquées dans ce chapitre, il peut sembler difficile de faire le bon choix. Quelles normes, référentiels ou lois s’appliquent ? Quelle force ? Quel protocole ? Faut-il utiliser plusieurs facteurs ? Si oui, lesquels ? Quelles assurances le stockage du vérificateur doit-il fournir ? Quelles assurances le protocole de transport réseau doit-il fournir ? Faut-il utiliser des facteurs physiques comme des cartes à puce ? Si oui, à quel cout ? Qu’utiliser quand on accède à une API ?
Pour ajouter à la complexité technique, il faut ajouter celles relatives aux humains. Quelle solution est la plus acceptable et réaliste ? Est-il réaliste de demander à un humain de mémoriser des mots de passe de plus de 12, voire 16 caractères, générés aléatoirement par une machine et sur 4 classes de caractères ? Que faire si un facteur est perdu ? Comment tenir compte des méthodes de hameçonnage et d’ingénierie sociale, et quel risque leur associer ?
En 2024, les capacités de calcul sont telles que la plupart des humains sont incapables de mémoriser un mot de passe ou une phrase de passe résistant à une attaque par recherche exhaustive, en particulier si la méthode de stockage des dérivées des mots de passe côté vérificateur est insuffisante. Les mauvaises pratiques du milieu46 et la complexité d’analyse d’une adresse réticulaire (Uniform Resource Locator (URL)) sont telles que même les spécialistes peinent à distinguer un lien légitime d’un lien redirigeant vers un site d’hameçonnage 47.
Ces conclusions ont mené les industries sensibles à déconsidérer les facteurs d’authentification basés sur la connaissance (mots de passe, codes PIN, jetons d’authentification), nécessitant un stockage assurant la confidentialité (HTTP digest, etc.) et ceux qui sont vulnérables aux attaques par rejeu ou par relais (mécanisme de preuve par divulgation (dont les TOTP), codes TAN, clés privées réutilisées auprès de plusieurs vérificateurs…). D’un autre côté, rares sont les organismes qui disposent du budget nécessaire pour fournir à tous leurs utilisateurs et utilisatrices des facteurs de possession tels que des cartes à puce, des clés USB implémentant U2F ou FIDO2, ou même des téléphones portables (Duo Push, Microsoft Authenticator). Ces moyens sont généralement réservés au public sensible, comme les équipes de sécurité et les équipes opérationnelles et d’administration.
Pour ces raisons, des mécanismes d’authentification reposant sur le standard W3C WebAuthn48 et utilisant des stockages logiciels plutôt que physiques (soft tokens) ont émergé, avec l’avènement des passkeys en 2023, principalement sous l’impulsion de Google, Apple et Microsoft.
Les passkeys sont des clés utilisées dans le cadre du protocole WebAuthn. Ce protocole prévoit qu’une clé privée distincte soit utilisée par chaque vérificateur (relying party dans la norme). Pour cela, WebAuthn utilise un identifiant unique (Uniform Resource Identifier (URI)) pour distinguer les vérificateurs, le cas typique étant l’adresse réticulaire (URL) du site web demandant une authentification. Chacune de ces clés privées est stockée dans un coffre-fort auquel le prouveur pourra avoir accès sur demande. Pour éviter l’inconvénient de la perte, ce coffre-fort est généralement synchronisé dans le cloud ; c’est le cas, par exemple, pour les passkeys gérées par Apple (stockage dans iCloud) ou par Bitwarden (stockage dans le coffre-fort de mots de passe). L’utilisateur ou l’utilisatrice n’a alors qu’à s’authentifier auprès du service qui stocke ce coffre-fort pour récupérer l’ensemble de ses passkeys.
Contrairement aux mots de passe qui pourraient être stockés dans ces mêmes coffres-forts, les passkeys sont par conception :
Contrairement aux facteurs de possession physiques, les passkeys sont par conception :
Enfin, les passkeys étant uniques à chaque vérificateur, elles offrent des propriétés intéressantes pour la vie privée. En effet, il n’existe aucun lien entre deux clés privées distinctes. Cela empêche donc plusieurs vérificateurs de se liguer en vue de tracer et corréler les activités d’un même utilisateur ou d’une même utilisatrice sur leurs systèmes d’information respectifs.
--- title: Authentification avec WebAuthn (simplifiée) --- sequenceDiagram autonumber box Client actor p as Peggy participant cf as Coffre-fort participant b as Navigateur end box Serveur participant v as Victor participant db as Base de données end p ->> b:"Je suis Peggy. Je veux accéder à https://broken-by-design.fr/" b --> v:"Je suis Peggy. Je veux accéder à https://broken-by-design.fr/" v ->> v:Tire un nonce v ->> b:"Prouve le. Voici un nonce." p ->> cf:Déverrouille son coffre-fort, par exemple avec un mot de passe b ->> cf:"Je visite https://broken-by-design.fr et voici le nonce" cf ->> cf:Vérifie que Peggy a déverrouillé le coffre-fort il y a peu (*user verification*) cf ->> cf:Récupère la clé associée à https://broken-by-design.fr/ cf ->> cf:Signe le nonce et le site visité cf ->> b:"Voici la signature" b ->> v:"Voici la signature" v ->> db:"C'est quoi la clé publique de Peggy ?" db ->> v:"Voici la clé publique de Peggy" v ->> v: Vérifie la signature alt La signature est valide v ->> b:"Bonjour Peggy!" b ->> p:"Bonjour Peggy!" else La signature est invalide v ->> b: "Je ne pense pas, non." b ->> p: "Je ne pense pas, non." end
L’autorisation est le fait d’accorder ou non, à un sujet (c’est-à-dire un acteur, une organisation, ou un groupe), à l’issue d’un contrôle d’accès, les droits, permissions ou privilèges, lui permettant d’effectuer une activité sur un objet ou une vue.
Derrière cette définition assez générique se cachent des réalités simples et intuitives, mais aussi des modèles de sécurité permettant l’application de politiques plus ou moins abstraites (modèles de Bell-Lapadula, Biba, Clark-Wilson, Multilevel Security (MLS)…). Ce chapitre détaillera ces différents modèles.
Les sujets, actions et objets soumis à un système de contrôle d’accès ont besoin d’être identifiés de manière à pouvoir y faire référence lors de l’écriture de règles de contrôle d’accès.
Pour les sujets, nous avons déjà discuté assez largement de la manière de les identifier dans ce cours.
Pour ce qui est des objets, l’identification peut être effectuée de manière explicite, par l’ajout d’une étiquette (label). Cette étiquette peut décrire une identité individuelle pour cet objet. Néanmoins, la plupart du temps, il s’agit plutôt d’une identité d’appartenance à un groupe. Par exemple, il pourrait s’agir d’une étiquette “objets correspondant à des données bancaires” ou “objets contenant des données personnelles”.
L’étiquetage s’effectue généralement par l’ajout d’une métadonnée associée à l’objet. Sous Linux, cela s’effectue le plus souvent avec les attributs étendus50.
L’étiquetage est le système le plus répandu d’identification des objets, mais il est également possible d’identifier un objet de manière intrinsèque, par exemple en fonction de son nom ou de sa localisation. Ce système est notamment utilisé par le Linux Security Module (LSM) AppArmor qui définit des politiques de sécurité sur des fichiers en fonction de leur chemin d’accès dans le système de fichiers. Un autre exemple est le contrôle d’accès sur un site web, en fonction de la section “chemin” d’une adresse réticulaire (URL Path).
La plupart des personnes manipulant un ordinateur sont familières avec le contrôle d’accès discrétionnaire (DAC), même si la désignation leur est inconnue.
Ce type de contrôle d’accès consiste à laisser la liberté au propriétaire d’un objet de déterminer les droits d’accès à ce dernier. C’est le modèle de contrôle d’accès par défaut sous Linux, avec les appels système chown(2)
et chmod(2)
qui permettent respectivement de changer le propriétaire d’un fichier et les droits (lecture, écriture, exécution) qui sont associés à l’utilisateur propriétaire, à un groupe d’utilisateurs, et aux autres utilisateurs.
Ce contrôle d’accès est parfaitement adapté pour la gestion du contrôle d’accès à des données personnelles. Néanmoins, dans une entreprise, le contrat de travail contient quasi systématiquement une clause de cession des droits patrimoniaux de l’ensemble des productions du personnel. Pour le dire plus vulgairement, l’entreprise est la propriétaire des documents produits. Comme il n’est pas raisonnable d’attendre du chef ou de la cheffe d’entreprise de prendre toutes les décisions d’attribution des droits, des politiques de sécurité sont établies, qui s’appliquent ensuite de manière verticale sur l’ensemble des objets produits par le personnel de l’entreprise. L’étiquetage entre alors en jeu.
Le contrôle d’accès obligatoire (Mandatory Access Control) a parfois été incorrectement appelé “contrôle d’accès mandataire” par les agents du gouvernement français, probablement pour des raisons de proximité phonétique avec “mandatory”…
Ce type de contrôle d’accès consiste en l’établissement d’une politique de sécurité qui s’applique de manière verticale à l’ensemble des sujets, des actions et des objets d’un système d’information.
Les politiques sont des descriptions abstraites des relations entre les sujets, les actions et les objets. Bien qu’elles puissent établir des règles à propos de sujets ou d’objets individuels spécifiques, elles portent plus généralement sur des étiquettes pouvant être associées à plusieurs sujets ou objets.
La littérature contient de nombreuses variantes et approches au contrôle d’accès obligatoire. Certaines sont assez intuitives, par exemple en attribuant des rôles aux sujets (Role-based Access Control (RBAC)). D’autres approches utilisent des attributs arbitraires associés aux sujets, actions ou objets (Attribute-based Access Control (ABAC)), ou encore des informations contextuelles à propos du sujet (Context-based Access Control (CBAC)) : (heure d’accès, géolocalisation, capacités du terminal, force de l’authentification, etc…).
Certaines approches au contrôle d’accès obligatoires rajoutent des couches d’abstraction supplémentaires, en bâtissant sur ceux déjà cités. Par exemple, le modèle de contrôle d’accès fondé sur l’organisation (Organization-based Access Control (OrBAC)) repose sur les approches par rôles (RBAC), par actions (Task-based Access Control (TBAC)), par vues (View-based Access Control (VBAC)) et par équipes (Team-based Access Control (TBAC, à nouveau…)). Le modèle OrBAC abstrait le triplet “sujets, action, objets” en un nouveau triplet “rôles, activités, vues”.
Des règles de contrôle d’accès peuvent alors être écrites concernant ce nouveau triplet en faisant abstraction du contexte d’implémentation, c’est-à-dire de l’organisation (société, association, etc.) pour laquelle elles sont écrites. Cela permet ainsi de les écrire une fois pour toutes, pour un nombre arbitraire d’organisations qui y auront recours.
Une couche de “traduction” spécifique à chaque organisation doit alors être utilisée pour transposer ces règles abstraites en des règles pragmatiques concernant des acteurs, les actions et les objets de chaque organisation.
L’approche par sécurité multiniveau (Multilevel Security (MLS)) est assez ancienne. Elle est particulièrement appréciée dans les domaines militaires et gouvernementaux, du fait de la verticalité intrinsèque de cette approche. Néanmoins, cette approche a également ses mérites en dehors du domaine exécutif. Elle est, par exemple, intéressante pour la centralisation des données de santé (monitoring) et de journalisation d’un système d’information.
Le principe général de la sécurité multiniveau est, en effet, d’établir une hiérarchie de niveaux d’autorisation. Les acteurs associés à un niveau sont alors autorisés à effectuer un jeu d’actions restreint avec les objets associés aux niveaux situés en dessous du niveau de l’acteur. Un autre jeu d’actions, généralement distinct et disjoint, est également autorisé pour cet acteur avec les objets associés aux niveaux situés au-dessus du niveau de l’acteur.
Parmi les modèles de sécurité reposant sur la sécurité multiniveau, on peut notamment citer le modèle de Bell-Lapadula51, le modèle Biba52, ou encore celui de Clark-Wilson53.
Le modèle Bell-Lapadula utilise la sécurité multiniveau à des fins de confidentialité. Le principe général est qu’un acteur situé à un certain niveau de sécurité ne peut qu’écrire aux niveaux supérieurs et ne peut que lire aux niveaux inférieurs. En anglais, on parle d’une approche “Write Up, Read Down (WURD)”. Avec cette approche, les acteurs de la hiérarchie peuvent concentrer les informations confidentielles, sans qu’aucune information notamment agrégée ne puisse redescendre.
Ce modèle est implémenté dans Linux à l’aide de SElinux (Security-Enhanced Linux), qui dispose d’une fonctionnalité multiniveau grâce aux étiquettes de niveaux de sensibilité.
Le modèle Biba utilise la sécurité multiniveau à des fins d’intégrité. Le principe général est comparable à celui de Bell-Lapadula, bien qu’il soit en quelque sorte inversé. Avec le modèle Biba, il n’y pas d’écriture aux niveaux supérieurs, et pas de lecture aux niveaux inférieurs. Ainsi, les niveaux les plus privilégiés sont protégés de toute interférence ou corruption de la part des niveaux inférieurs. En anglais, on parle d’une approche “Read Up, Write Down (RUWD)”.
Ce modèle peut être adroitement utilisé conjointement avec le modèle de Bell-Lapadula afin d’agréger des données confidentielles au niveau du commandement, et permettre ensuite au commandement de faire redescendre des ordres qui sont fonction de ces données agrégées.
Le modèle de Clark-Wilson s’intéresse également à l’intégrité. Son approche est plus dynamique et modélise le triplet “sujet,programme, objets”. Ce triplet signifie que les sujets ne peuvent manipuler les objets que par des programmes spécifiques. Ceci est plus restrictif que dans les autres modèles où le contrôle d’accès s’effectue en fonction de l’acteur, sans tenir compte de comment il y accède.
Ce modèle est notamment implémentable sous Linux grâce aux politiques de contrôles des types (type enforcement (TE)) de SElinux. Le type enforcement permet d’associer notamment à chaque utilisateur système ou rôle (ce qui est une autre notion de SElinux), à chaque programme exécutable, à chaque fichier, à chaque socket un type. Une politique TE régit ensuite les interactions entre les types (écriture, lecture, exécution, modification des métadonnées, etc.), ainsi que les transitions entre les types : tel utilisateur de type W peut exécuter un programme de type X, ce qui lui permet de lire les fichiers de type Y et d’écrire les fichiers de type Z.
Le modèle de Brewer et Nash consiste à appliquer une politique de sécurité permettant de prévenir les conflits d’intérêts, notamment en matière commerciale. Dans ce modèle, le contrôle d’accès est dynamique ; par défaut l’acteur a virtuellement accès à toutes les données. Néanmoins, en fonction des données auxquelles il accède, il se voit au fur et à mesure restreindre l’accès à d’autres données. Par exemple, si les sociétés A et B sont concurrentes, accéder aux données de la société A fait que l’on perdra automatiquement les accès aux données de la société B.
Un exemple d’implémentation de ce modèle est l’outil StemJail54 pour Linux, développé par Mickaël Salaün (ANSSI), avec Marion Daubignard (ANSSI) et sous la coulpe d’Hérvé Debar (SudParis Télécom), dans le cadre de la thèse de doctorat de Mickaël.
Avec l’approche Role-based Access Control (RBAC), des rôles sont attribués à des sujets. Comme vu précédemment dans ce cours, le terme de sujet recouvre plusieurs réalités : des acteurs mais aussi des groupes d’acteurs. Or, dans certaines définitions de ce que sont les rôles, il est retenu que les rôles sont des groupes d’acteurs et de permissions, tandis que d’autres définitions retiennent que les rôles sont des collections de permissions55. Ainsi, certaines implémentations considérant que les rôles sont des groupes d’acteurs et de permissions n’implémentent pas du tout la notion de groupes d’acteurs (sans permissions), considérant celle-ci redondante avec celle des rôles. Pour rajouter un peu de confusion, certaines implémentations ne nomment pas les rôles “rôles” mais “groupes” (e.g. Gitlab) ou “équipes” (e.g. Gitea/Forgejo).
D’une manière générale, il est fortement déconseillé d’attribuer des permissions à des acteurs de façon nominative, à moins qu’il ne soit possible de placer un commentaire explicite à côté de ces permissions accordées nominativement, afin de justifier leur attribution.
Prenons l’exemple d’un personnel d’entreprise, inspiré d’un cas réel : au cours de sa vie professionnelle au sein de cette entreprise, ce personnel intègre une équipe de développement et obtient les permissions nécessaires à l’accomplissement de son affectation. Plus tard, ce même personnel réoriente sa carrière et devient ingénieur avant-vente, et se voit attribuer en conséquence de nouvelles permissions pour l’accomplissement de sa nouvelle affectation. Finalement, ce personnel bascule totalement dans l’équipe commerciale, et obtient encore de nouvelles permissions. Comme prévu dans la politique de sécurité de la société, les permissions sont auditées annuellement, afin de s’assurer que personne ne détient des permissions indues. Lorsque la personne en charge de l’audit vérifiera les permissions de ce personnel, il lui sera très difficile de s’assurer de la légitimité de chaque permission unitaire sans investigation. Si les permissions avaient été accordées en fonction de l’appartenance ou non à un groupe d’acteurs, il suffirait de contrôler la pertinence de l’appartenance aux groupes des développeurs, des avant-ventes et des commerciaux.
En conséquence, même lorsque la notion de rôles est celle de groupes d’acteurs et de permissions, il est fortement conseillé de créer des rôles composés uniquement d’acteurs et de rôles composés exclusivement de permissions et de créer une hiérarchie entre ces rôles, de façon à ce que les rôles “groupes” héritent des permissions des rôles “permissions”.
Les protocoles OAuth2 et OpenID Connect sont détaillés dans cette section en préparation du TP compagnon de ce cours. Il existe d’autres protocoles d’autorisation, comme Kerberos ou SAML, qui ne seront pas abordés dans ce cours, mais qui offrent des propriétés de sécurité intéressantes ou comparables.
OAuth2 est un protocole standard d’autorisation, extensible, principalement utilisé dans le contexte web. Une partie de sa spécification, ce qui est appelé le “cadriciel OAuth2” (framework), repose dans la RFC 674956. Cette RFC est également completée par les RFC 675057 et 825258. Le principe général d’OAuth2 repose sur un protocole impliquant quatre participants :
--- title: Représentation simplifiée des interactions entre les parties du protocole OAuth2 --- sequenceDiagram autonumber actor p as Propriétaire actor a as Serveur d'autorisation actor r as Serveur de ressources actor c as Client c ->> r:"Je souhaite accéder à la ressource X." r ->> c:"Il faut un jeton d'accès. Va voir le serveur d'autorisation." c ->> a:"J'aurais besoin d'un jeton d'accès pour la ressource X. Je redirige le propriétaire vers toi." a ->> p:"T'es qui ?" p ->> a:"Je suis Peggy, et en voici la preuve." a ->> a:Vérifie la preuve. a ->> p:"OK, Peggy. J'ai ce Client qui voudrait accéder à X dont tu es propriétaire. T'en penses quoi ?" p ->> a:"OK pour donner accès à Client à la ressource X." a ->> c:"OK, voici un jeton d'accès pour X." c ->> r:"Je souhaite accéder à la ressource X. Voici le jeton d'accès." r ->> r:Vérifie le jeton d'accès. alt Le jeton d'accès est valide r ->> c:"Voici la ressource X." else Le jeton d'accès est invalide, forgé ou expiré r ->> c:"Accès refusé." end
Le serveur de ressources et le serveur d’autorisation ont établi une relation de confiance au préalable. Cette relation de confiance permet au serveur de ressources de reconnaitre et vérifier des jetons d’accès émis par le serveur d’autorisation.
De même, la personne propriétaire d’une ressource a préalablement établi une relation de confiance avec le serveur d’autorisation ; elle est notamment capable de lui prouver son identité, d’une part, et de le convaincre qu’elle est propriétaire d’une certaine donnée, d’autre part.
Finalement, la tierce partie et le serveur d’autorisation ont également préalablement établi une relation de confiance qui permet à la tierce partie de prouver son identité au serveur d’autorisation.
Ainsi, lorsque la tierce partie manifeste le besoin d’accéder à la ressource, elle sollicite le serveur d’autorisation pour obtenir un jeton d’accès et s’authentifie auprès de lui. Après avoir vérifié l’identité de la personne propriétaire de la ressource, le serveur d’autorisation lui demande l’accord pour délivrer un jeton d’accès à cette ressource pour cette tierce partie spécifique. En cas d’accord, un jeton est délivré. La tierce partie peut alors contacter le serveur de ressources et présenter le jeton d’accès. Le serveur de ressources vérifie le jeton d’accès, et s’il est valide, donne accès à la ressource.
Ce protocole permet de délivrer des autorisations d’accès à des ressources protégées, avec une granularité réglable, sans révéler à la tierce partie l’identité ou les moyens d’identification (les “authentifiants”) du propriétaire de la ressource. De surcroit, ce protocole permet de délivrer à la tierce partie des jetons d’accès à usage restreint : ils sont incessibles et potentiellement limités dans le temps.
Une critique récurrente qui peut être adressée contre le cadriciel d’OAuth2 est la multitude de ces modes opératoires, certains étant par essence d’une sécurité relativement douteuse. C’est notamment le cas du mode implicite, ou lorsque sont utilisés des clients “publics”. Ce cours ne rentrera pas plus avant dans ces considérations, mais de plus amples informations peuvent être trouvées dans la RFC de référence, à la section “Considérations de sécurité”.
Une utilisation “abusive” ou “détournée” du protocole d’OAuth2 est souvent constatée pour l’authentification décentralisée. Dans ce contexte d’usage, le serveur de ressources et le serveur d’autorisation sont la même entité. Lorsqu’une personne veut s’authentifier auprès d’une application tierce, elle demande à cette application de demander une autorisation d’accès au serveur d’autorisation. Le serveur d’autorisation demande à cette personne de s’authentifier, puis renvoie à la tierce partie un jeton d’accès pour une ressource quelconque contenant une information identifiant la personne qui s’est authentifiée. Si la tierce partie est en mesure d’obtenir cette ressource grâce au jeton d’accès, alors elle peut déduire que la personne a été capable de prouver son identité au serveur d’autorisation.
Cette utilisation abusive a été normalisée par une extension au protocole OAuth2 : OpenID Connect.
OpenID Connect (OIDC)59 est une extension au protocole OAuth2. Elle rajoute notamment une couche d’identité, qui permet de normaliser la communication de l’identité d’une personne connue du serveur OIDC à la tierce partie (appelée en anglais relying party), et de fournir également des informations complémentaires à son sujet. Ces informations sont appelées des assertions (claims), qui peuvent être de nature arbitraire, tant qu’elles sont exprimables dans le format JWT (JSON Web Token)60.
Le principe général d’OAuth 2 est appliqué avec OpenID Connect. La différence majeure est que le serveur d’autorisation est également le serveur de ressources, et que la ressource consultée est un document appelé “ID Token”, contenant des assertions relatives à la personne s’étant authentifiée au serveur d’autorisation.
Le document ID Token contient diverses assertions requises ou optionnelles. Les assertions requises sont :
iss
: “issuer” : l’identifiant de l’émetteur de cet ID Token ;sub
: “subject” : l’identifiant de la personne cherchant à prouver son identité à la tierce partie ;aud
: “audience” : l’identifiant de la tierce partie ;exp
: “expiry date” : la date d’expiration de cet ID Token ;iat
: “issued at” : la date d’émission de cet ID Token.Les assertions suivantes sont parfois requises, parfois optionnelles :
auth_time
: “authentication time” : heure de la dernière authentification réussie de la personne cherchant à prouver son identité à la tierce partie auprès du serveur OpenID Connect. Cette assertion est requise si l’application tierce a explicitement exprimé le besoin d’en connaitre à propos cette information.nonce
: une valeur arbitraire ajoutée à l’ID Token à la demande de la tierce application, en vue de contrer des attaques par rejeu éventuelles.Les serveurs OpenID Connect peuvent être généralement configurés pour ajouter des assertions additionnelles arbitraires. Certaines peuvent ainsi spécifier les groupes auxquels appartient le sujet de l’ID Token ou les rôles dont il disposerait.
User-managed Access (UMA) est une autre extension au protocole OAuth2. Spécifiée par la Kantara Initiative61, elle permet au propriétaire d’une ressource d’établir à l’avance des règles régissant l’émission de jetons d’accès à cette ressource. L’application tierce sera alors autonome pour obtenir des jetons d’accès à cette ressource sous réserve de satisfaction des règles édictées par le propriétaire et sans interaction explicite avec ce dernier.
Cette extension permet notamment la création d’un référentiel central d’autorisation, seule source de vérité des autorisations d’accès sur l’ensemble des ressources d’un système d’information.
Hélas, s’il y a bon nombre de fournisseurs de service pour le protocole UMA, son adoption par les applications tierces est encore modeste.
Je tiens à remercier mes relecteurs et relectrices pour leurs contributions à ce cours. Un merci tout spécial à @karl@infosec.exchange et @bortzmeyer@mastodon.gougere.fr pour leurs suggestions d’amélioration nombreuses et détaillées.
Le contenu de ce cours ne saurait les engager.
Ce cours est publié sous licence CC-BY.
Vous êtes autorisé à :
L’Offrant ne peut retirer les autorisations concédées par la licence tant que vous appliquez les termes de cette licence.
Selon les conditions suivantes :
https://learn.microsoft.com/fr-fr/windows-server/identity/ad-ds/plan/using-the-organizational-domain-forest-model ↩︎
https://cyber.gouv.fr/secnumcloud-pour-les-fournisseurs-de-services-cloud ↩︎ ↩︎
version 3.2, chapitre 9.6, alinéa a ↩︎
https://www.legifrance.gouv.fr/cnil/id/CNILTEXT000046693390 ↩︎
https://www.legifrance.gouv.fr/cnil/id/CNILTEXT000042203965/ ↩︎
https://www.legifrance.gouv.fr/cnil/id/CNILTEXT000047552103 ↩︎
https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:32014R0910 ↩︎
https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=celex%3A32015L2366 ↩︎
https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000035430451 ↩︎
https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000035407334/ ↩︎
https://ec.europa.eu/digital-building-blocks/sites/display/DIGITAL/eIDAS+eID+Profile ↩︎
https://eur-lex.europa.eu/legal-content/FR/ALL/?uri=CELEX:32015R1502 ↩︎ ↩︎
https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000035720606 ↩︎
https://cyber.gouv.fr/le-referentiel-general-de-securite-version-20-les-documents ↩︎
https://cyber.gouv.fr/publications/recommandations-relatives-lauthentification-multifacteur-et-aux-mots-de-passe ↩︎
https://www.cloudflare.com/fr-fr/learning/bots/what-is-credential-stuffing/ ↩︎
https://jankrissler.blogspot.com/2016/09/hacker-fakes-german-ministers.html ↩︎
https://www.lemagit.fr/conseil/Key-Management-System-KMS-une-pierre-angulaire-du-chiffrement ↩︎
Une des propriétés de sécurité attendues des fonctions de hachage cryptographiques est qu’il soit virtuellement impossible de déterminer, autrement que par la recherche exhaustive, une valeur qui, passée à la fonction de hachage en entrée, produirait un résultat connu. ↩︎
Le serveur peut également stocker une dérivée du mot de passe, mais pour ce protocole, cette dérivée de mot de passe a la même sensibilité que le mot de passe lui-même : le connaitre est suffisant pour s’authentifier. ↩︎
https://fr.wikipedia.org/wiki/Preuve_%C3%A0_divulgation_nulle_de_connaissance#La_grotte_d'Ali_Baba ↩︎
https://fr.wikipedia.org/wiki/Protocole_d%27authentification_de_Schnorr ↩︎
Les protocoles à divulgation nulle de connaissance sont des protocoles probabilistes. Le vérificateur ne dispose jamais d’une preuve formelle de l’identité ; il acquiert juste une conviction reposant sur une probabilité écrasante que le prouveur connait ou possède le secret prouvant son identité. Le seuil de probabilité à partir duquel il est convaincu est paramétrable et à la discrétion du vérificateur. ↩︎
https://www.whatsapp.com/security/WhatsApp_Security_Encrypted_Backups_Whitepaper.pdf ↩︎
https://www.cloudflare.com/fr-fr/learning/bots/what-is-credential-stuffing/ ↩︎
https://www.scottbrady91.com/authentication/beware-of-password-shucking ↩︎
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0777 ↩︎
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-31497 ↩︎
Il semble très difficile d’astreindre les départements marketing et communications à utiliser uniquement des noms de domaine bien identifiés, que les utilisateurs et utilisatrices finaux sont habitués à reconnaitre… ↩︎
https://github.com/orangetw/My-Presentation-Slides/blob/main/data/2019-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdfs ↩︎
Le standard WebAuthn requiert la vérification de l’identité du vérificateur. Cette vérification est généralement faite à l’aide de TLS et de l’infrastructure de gestion de clés “web”. Si un attaquant réussit à disposer de la clé privée associée à un certificat légitime pour un vérificateur donné, alors il sera en mesure d’effectuer tout de même des attaques relais. WebAuthn dispose d’une mécanique appelée “channel binding” ou “token binding” permettant de prévenir totalement les attaques par relais, mais cette fonctionnalité n’a jamais été implémentée à large échelle. ↩︎
https://websites.umich.edu/~cja/LPS12b/refs/belllapadula1.pdf ↩︎
https://www.researchgate.net/publication/235043659_Integrity_Considerations_for_Secure_Computer_Systems ↩︎
https://groups.csail.mit.edu/ana/Publications/PubPDFs/A%20Comparison%20of%20Commercial%20and%20Military%20Computer%20Security%20Policies.pdf ↩︎
https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html ↩︎