Precedent Haut Suivant


5.2.4 -  Les mécanismes d’autorisation :

Le service d'autorisation décide d'autoriser ou non les actions entreprises par des processus, en se basant sur les attributs d'autorisation contenus dans le jeton de chaque processus.

 

Parmi les attributs d'autorisation, les différents SID sont utilisés par le contrôle d'accès, mécanisme qui permet de contrôler quels acteurs principaux ont accès aux objets et de quelles façons. Les privilèges sont eux utilisés lorsque l'autorisation par contrôle d'accès n'est pas adaptée.

5.2.4.A -  Le contrôle d’accès :

Le contrôle d'accès a lieu dans le contexte d'un processus accédant à un objet. Pour un processus, l'accès à un objet se fait toujours via une référence (handle), obtenue lors de l'ouverture de l'objet, via les fonctions de l'API Win32 du type OpenXxx() et CreateXxx(). Il est important de retenir que le contrôle d'accès, de même que l'audit, ont lieu lors de l'ouverture d'un l'objet. Si le contrôle d'accès valide l'ouverture d'un objet avec certaines permissions, il n'y a ensuite plus de contrôle pour cet objet, exceptés ceux s'assurant que l'objet est utilisé dans les limites de ce qui a été autorisé lors de son ouverture.

 

Par exemple, si au moment de l'ouverture en lecture seule d'un fichier par un processus, le fichier était en lecture et écriture pour l’acteur principal Administrateur, une tentative d'écriture dans le fichier ne sera pas autorisée puisque le fichier a été ouvert en lecture seule. Si le fichier est fermé puis ré-ouvert en lecture-écriture, les deux types d'accès seront autorisés tant que le fichier reste ouvert, même si, entre temps, le droit d'écriture sur ce fichier est retiré à l’acteur principal Administrateur.

 

Le contrôle d'accès fonctionne en faisant le rapprochement entre trois éléments : les permissions spécifiées lors de l'ouverture d'un objet, le descripteur de sécurité de l'objet accédé et le jeton du processus (attributs d'autorisation) réalisant l'accès.

5.2.4.B -  La gestion des permissions :

Lorsqu'un processus ouvre une référence à un objet, il précise quels types d'accès il veut réaliser sur l'objet, via un masque de permissions décrivant les permissions sur l'objet dont il souhaite disposer. Si ces permissions sont compatibles avec le descripteur de sécurité de l'objet, une référence à l'objet est accordée, le système se contentant ensuite de vérifier que les types d'accès font partie de ceux spécifiés lors de l'ouverture de l'objet. Dans les fonctions de l'API Win32 du type OpenXxx() et CreateXxx(), le masque de permissions est fourni dans le paramètre de nom dwDesiredAccess.

 

Un masque de permissions est une valeur de 32 bits, subdivisée en 4 : permissions standard (8 bits), permissions spécifiques (16 bits), permissions génériques (4 bits) et divers drapeaux (4 bits).

 

Les permissions standard sont des permissions qui s'appliquent à tous les types d'objets. Cinq sont actuellement définies :

-                     suppression de l'objet (DELETE) ;

-                     lecture du contenu du descripteur de sécurité de l'objet (READ_CONTROL) ;

-                     changement du propriétaire de l'objet (WRITE_OWNER) ;

-                     changement de la liste de contrôle d'accès de l'objet (WRITE_DAC) ;

-                     autorisation de se synchroniser sur cet objet (SYNCHRONIZE).

 

Les permissions spécifiques ne s'appliquent qu'à un type d'objet donné. Par exemple, pour un objet du type processus, une permission, PROCESS_TERMINATE, est définie pour autoriser la terminaison d'un processus.

 

Enfin, quatre permissions génériques sont définies :

-                     lecture (GENERIC_READ);

-                     écriture (GENERIC_WRITE);

-                     exécution (GENERIC_EXECUTE) ;

-                     les trois à la fois (GENERIC_ALL).

Elles s'appliquent à tous les types d'objets et permettent un polymorphisme des permissions, chacune des 4 permissions génériques étant équivalente à une liste de permissions standard et spécifiques. Par exemple, la permission générique de lecture (GENERIC_READ) sur un objet de type clé de la base de registres accorde la permission standard READ_CONTROL et les trois permissions spécifiques KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS et KEY_NOTIFY. Cette possibilité est intéressante pour le paramétrage des permissions sur les nouveaux objets créés.

5.2.4.C -  Descripteur de sécurité :

A tout objet sécurisable est associé un descripteur de sécurité (security descriptor, abrégé en SD), qui contient trois informations principales :

-                     le SID du propriétaire de l'objet ;

-                     sa liste de contrôle d'accès discrétionnaire (DACL) ;

-                     sa liste de contrôle d'accès système (SACL).

 

Tout objet a un propriétaire, dont le SID est stocké dans le SD. Le propriétaire d'un objet a toujours le droit de lire et de modifier la DACL des objets lui appartenant. C'est pour cette raison que le contrôle d'accès est qualifié de discrétionnaire, étant à la discrétion du propriétaire.

 

La DACL est simplement une liste d'entrées de contrôle d'accès (access control entry, abrégée en ACE) listant quels accès sont possibles à quels SID. Ces SID peuvent désigner des acteurs principaux uniques, des groupes locaux ou globaux.

 

Une ACE peut être positive ou négative : si elle est positive, elle accorde un type d'accès ; si elle est négative, elle refuse un type d'accès. Le type d'accès est spécifié sous la forme d'un masque de permissions.

5.2.4.D -  Jeton de sécurité :

Un jeton est attaché à un processus et définit son contexte de sécurité. Son contenu se subdivise en trois catégories :

-                     identité et attributs d'autorisation ;

-                     sécurité par défaut pour les nouveaux objets créés ;

-                     divers paramètres.

 

Pour le contrôle d'accès, les attributs d'autorisation utilisés sont les SID. Il y a au moins le SID du propriétaire du processus puis la liste des SID des groupes globaux (au niveau du domaine) et des groupes locaux (alias, au niveau du système local) dont l’acteur principal fait partie. Sont également présents un SID indiquant le type de session de connexion (par exemple, interactive) ainsi qu'un SID identifiant la session de connexion.

5.2.4.E -  Algorithme du contrôle d’accès Windows :

L'algorithme utilisé pour le contrôle d'accès utilise trois éléments : le masque de permissions représentant le type d'accès demandé, le descripteur de sécurité représentant la protection de l'objet et le jeton du processus, contenant les attributs d'autorisation.

 

L'algorithme utilise un entier de la même taille qu'un masque de permissions (32 bits), qui sert d'accumulateur des permissions accordées. Il est initialisé à zéro au début de l'algorithme. Le fonctionnement de l’algorithme est le suivant :

-                     le système remplit l'accumulateur avec les permissions implicites. Si les permissions ainsi accumulées ne sont pas suffisantes, l'algorithme se poursuit.

-                     Chaque entrée (ACE) de la DACL est examinée en séquence. Si une ACE autorise certaines permissions d'accès pour l'un des SID contenu dans le jeton, ces permissions sont accumulées.

-                     L'algorithme se poursuit jusqu'à ce que l'un des trois événements suivants se produise : toutes les permissions présentes dans le masque de permissions spécifié lors de l'accès ont été accumulées, auquel cas l'accès est accordé ; une ACE refusant un accès à un SID contenu dans le jeton est rencontrée, auquel cas l'accès est refusé ; la fin de la DACL est atteinte sans que toutes les permissions aient été accumulées, auquel cas l'accès est également refusé.

 


La première étape permet de donner certaines permissions dites implicites. Par exemple, nous avons vu que le propriétaire d'un objet possède toujours les permissions de lire et de modifier la DACL de cet objet. Un autre cas est celui d'un jeton possédant le privilège de modifier le propriétaire de tout objet, ce qui donne implicitement la permission correspondante sur tout objet accédé.

 

Dans la seconde étape, chaque ACE est examinée et prise en compte si, d'une part, elle concerne l'un des SID du jeton et, d'autre part, elle concerne l'une des permissions demandées dans le masque de permissions. Toute ACE d'interdiction interrompt le parcours et provoque un refus d'accès. L'ordre des ACE dans une DACL est donc important, les ACE d'interdiction devant apparaître devant les ACE d'autorisation. Le système se charge de faire respecter cet ordre pour les ACE éditées via l'interface graphique de l'éditeur de contrôle d'accès, tel que celui utilisé par l'explorateur de fichiers.

5.2.4.F -  Origine des descripteurs de sécurité :

L’accès aux objets est protégé grâce à la structure de descripteur de sécurité. Le présent paragraphe présente le mécanisme de création de ces descripteurs de sécurité.

 

Lors de l’examen de la structure du jeton de sécurité, il a été démontré la nécessité d’obtenir  en plus des attributs d'autorisation, des informations permettant de paramétrer la sécurité des objets créés par le processus. Dans les fonctions de l'API Win32 permettant de créer des objets, il est toujours possible de passer une structure de type LPSECURITY_ATTRIBUTES, à partir de laquelle sera construit le descripteur de sécurité du nouvel objet. Cependant, cette approche est lourde, obligeant à spécifier pour chaque objet des paramètres de sécurité. Il est souvent d'usage de mettre ce paramètre à NULL : dans ce cas, le descripteur de sécurité est construit à partir des paramètres de sécurité trouvés dans le jeton. Ceci permet donc de réduire le code ayant à manipuler la sécurité des objets, tout en assurant la cohérence des permissions sur les objets créés.

 

Les informations pour la sécurité des nouveaux objets sont le propriétaire par défaut ainsi qu'une DACL par défaut. La DACL devant être valable pour tous les types d'objets, les permissions autorisées sont uniquement des permissions génériques ou standard. C'est là tout l'intérêt de disposer de permissions génériques polymorphes : il est ainsi possible d'accorder la permission générique de lecture à un acteur principal donné pour tous les nouveaux objets créés, cette permission générique étant traduite en terme de permissions standard et spécifiques, suivant le type d'objet.

 

Dans le cas d'objets stockés dans une structure hiérarchique, tels que des fichiers contenus dans des répertoires ou des objets contenus dans des conteneurs d'Active Directory, il existe également une fonctionnalité d'héritage des DACL. Ceci évite par exemple d'avoir à spécifier explicitement les DACL de fichiers contenus dans un même répertoire. Il suffit alors de configurer la DACL sur le répertoire et d'indiquer que les fichiers (voire les répertoires) situés sous ce répertoire en héritent.

 

Dans Windows NT 4.0, l'héritage des ACL était géré de façon manuelle : il n'y avait pas de mécanisme automatique pour propager les ACE héritées en cas de changement sur un objet parent. De plus, il n'y avait pas de distinction entre une ACE héritée et une ACE propre à l'objet. Ce modèle d'héritage n'était donc pas très flexible en pratique.

 

Dans Windows 2000, le modèle d'héritage a été étendu, notamment à cause de l'importance de l'héritage pour les objets contenus dans l'annuaire Active Directory. Dans ce nouveau modèle, l'héritage est dynamique, de sorte que lorsque les permissions sont modifiées sur un objet parent, il y a propagation automatique aux objets contenus. De plus, les ACE héritées sont marquées comme telles, afin de les distinguer des ACE propres à un objet. Il devient ainsi possible d'utiliser l'héritage pour gérer de façon globale des permissions, tout en gardant la possibilité d'écraser, de façon locale, certaines permissions. Du coup, les ACE héritées doivent apparaître après les ACE propres à un objet, afin qu'il soit possible de redéfinir des permissions par rapport à celles héritées.

5.2.4.G -  Les privilèges sous Windows :

Les privilèges permettent une autre forme d'autorisation que le contrôle d'accès. En effet, le contrôle d'accès n'est pas adapté à toutes les situations.

 

L'exemple typique dans lequel un privilège est plus adapté que le contrôle d'accès consiste à étudier les privilèges de sauvegarde et de restauration de fichiers. Lorsqu'ils sont donnés à un acteur principal, ils permettent de lire et écrire tous fichiers du système, en contournant les mécanismes de contrôle d'accès. L'intérêt d'utiliser un privilège pour autoriser ce genre de tâche est double. En premier lieu, il évite d'avoir à autoriser les opérateurs de sauvegarde à lire ou écrire tous les fichiers du système. Cette technique obligerait à modifier la liste de contrôle d'accès de chaque fichier. En second lieu, il ne rend possible la lecture et l'écriture de fichiers que dans le cadre d'opérations de sauvegarde. En effet, pour pouvoir sauvegarder ou restaurer un fichier, il faut activer ce privilège et ouvrir le fichier à sauvegarder ou restaurer avec un drapeau spécial.

 

Les privilèges sont également utilisés lorsque le contrôle d'accès n'est pas possible, aucun objet n'ayant été défini pour autoriser ce que le privilège permet. Par exemple, il existe des privilèges permettant d'arrêter le système ou d'en changer l'heure, l'hypothétique objet de type SYSTEM, sur lequel il serait possible de définir les permissions d'arrêt et de changement d'heure, n'existant pas.

 

Les privilèges sont des attributs d'autorisation locaux et n'ont donc de sens que sur le système local. Ils sont affectés à des principaux par l'administrateur du système, pour lequel ils sont connus sous le nom de droits utilisateurs. Les privilèges se retrouvent dans les jetons des processus mais ne sont, pour la plupart, pas activés. Ils doivent donc être explicitement activés avant de pouvoir être utilisés. Un programme correctement écrit n'active les privilèges nécessaires que le temps d'exécuter une action privilégiée.


Precedent Haut Suivant