Add authz course ; fix trailing spaces

This commit is contained in:
Florian Maury 2024-03-20 19:11:57 +01:00
parent 5951dcb201
commit 4e89cb5cb3

View file

@ -1009,6 +1009,206 @@ sequenceDiagram
end end
``` ```
# Autorisation
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.
## Étiquetage explicite ou intrinsèque
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 étendus[^xattr].
[^xattr]: https://man7.org/linux/man-pages/man7/xattr.7.html
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).
## Contrôle d'accès discrétionnaire (DAC)
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.
## Contrôle d'accès obligatoire (MAC)
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.
### Les modèles théoriques
#### Les modèles de MAC classiques
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...).
#### OrBAC
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.
#### Sécurité multiniveau
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-Lapadula[^bl-model], le modèle Biba[^biba-model], ou encore celui de Clark-Wilson[^cw-model].
[^bl-model]: https://websites.umich.edu/~cja/LPS12b/refs/belllapadula1.pdf
[^biba-model]: https://www.researchgate.net/publication/235043659_Integrity_Considerations_for_Secure_Computer_Systems
[^cw-model]: https://groups.csail.mit.edu/ana/Publications/PubPDFs/A%20Comparison%20of%20Commercial%20and%20Military%20Computer%20Security%20Policies.pdf
##### Le modèle Bell-Lapadula
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
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 module de Clark-Wilson
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.
#### Modèle de Brewer et Nash ou de la muraille de Chine
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 StemJail[^stemjail] 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.
[^stemjail]: https://stemjail.github.io/
### Des rôles et des groupes
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 permissions[^groupsvsroles]. 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).
[^groupsvsroles]: https://profsandhu.com/workshop/role-group.pdf
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".
## OAuth2, OpenID Connect et assertions de sécurité
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
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 6749[^RFC6749]. Cette RFC est également completée par les RFC 6750[^RFC6750] et 8252[^RFC8252]. Le principe général d'OAuth2 repose sur un protocole impliquant quatre participants :
* une personne propriétaire d'une ressource (en anglais "*resource owner*");
* un serveur de ressources (en anglais "*resource server*");
* une tierce partie souhaitant obtenir accès à cette ressource ; il s'agit généralement d'une application (en anglais "*client*" ou "*relying party*");
* un serveur d'autorisation (en anglais "*authorization server*).
[^RFC6749]: https://www.rfc-editor.org/rfc/rfc6749.html
[^RFC6750]: https://www.rfc-editor.org/rfc/rfc6750.html
[^RFC8252]: https://www.rfc-editor.org/rfc/rfc8252.html
```mermaid
---
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
OpenID Connect (OIDC)[^oidc] 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*)[^jwt].
[^oidc]: https://openid.net/developers/specs/
[^jwt]: https://www.rfc-editor.org/rfc/rfc7519.html
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
User-managed Access (UMA) est une autre extension au protocole OAuth2. Spécifiée par la Kantara Initiative[^umaspec], 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.
[^umaspec]: https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html
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.
# Remerciements # Remerciements
Je tiens à remercier mes relecteurs et relectrices pour leurs contributions à ce cours. Un merci tout spécial à [@karl@infosec.exchange](https://infosec.exchange/@karl) et [@bortzmeyer@mastodon.gougere.fr](https://mastodon.gougere.fr/@bortzmeyer) pour leurs suggestions d'amélioration nombreuses et détaillées. Je tiens à remercier mes relecteurs et relectrices pour leurs contributions à ce cours. Un merci tout spécial à [@karl@infosec.exchange](https://infosec.exchange/@karl) et [@bortzmeyer@mastodon.gougere.fr](https://mastodon.gougere.fr/@bortzmeyer) pour leurs suggestions d'amélioration nombreuses et détaillées.