🏢Active DirectoryGroups

revue de groupe AD vide : vérifier un groupe privilégié

Vérifiez les groupes AD privilégiés vides avant de clore une Info : rapprochez identité, lectures d’appartenance et configuration voulue par le responsable.

Younes AZABARPar Younes AZABAR10 min de lecture
revue de groupe AD vide : vérifier un groupe privilégié

Ce qu’établit la revue d’un groupe AD privilégié vide

Une revue de groupe AD vide vise à déterminer si l’absence de membres signalée dans un groupe privilégié est fiable et intentionnelle. Un résultat informatif constitue un point de départ pour la vérification : identifier le groupe, établir ce que la collecte a effectivement lu, puis consigner la décision du responsable. La clôture du constat doit préserver ces preuves plutôt que modifier l’appartenance dans le seul but de faire disparaître le résultat.

Microsoft documente plusieurs groupes d’opérateurs sans membres par défaut, notamment Account Operators, Backup Operators, Print Operators et Server Operators. Leur état vide peut donc être attendu. La même référence explique les capacités administratives de ces groupes et les restrictions concernant la suppression des groupes intégrés. Consultez la référence des groupes de sécurité Active Directory pour le groupe examiné.

La distinction utile sépare l’appartenance inconnue, la présence de membres confirmée et l’absence intentionnelle de membres confirmée dans un périmètre défini. Ces résultats nécessitent des suites différentes. Un attribut manquant, une commande en échec et un groupe vide approuvé ne doivent pas recevoir le même libellé de clôture.

Pourquoi les preuves d’appartenance peuvent être incomplètes

L’attribut member de l’objet groupe est multivalué et utilise la syntaxe des noms distinctifs. Sa lecture fournit une vue au niveau de l’attribut. La revue doit également prendre en compte les groupes imbriqués et, lorsque cela s’applique, l’appartenance au groupe principal portée par les comptes.

La pagination des résultats LDAP et la récupération des attributs par plages résolvent des problèmes différents. La pagination récupère des lots d’objets ; la récupération des attributs par plages récupère des lots de valeurs d’un même attribut multivalué. Un collecteur peut terminer la pagination de sa recherche de groupes sans parvenir à assembler toutes les valeurs d’appartenance d’un groupe donné. Lors du diagnostic d’un export LDAP brut, examinez les noms des attributs renvoyés et vérifiez que toutes les plages ont été récupérées.

La référence de schéma primaryGroupID définit cet attribut de compte comme l’identificateur relatif de son groupe principal. Un export limité aux groupes n’examine pas cet attribut des comptes. Notre article sur l’appartenance via primaryGroupID omise par les exports limités à member explique ce chemin d’appartenance distinct. Utilisez-le pour comprendre les limites de couverture ; cette revue ne demande ni de modifier primaryGroupID ni de reproduire la technique d’abus.

Avant d’interpréter un résultat vide, consignez précisément le DC, le domaine, la base de recherche, l’identité de collecte et les limites pertinentes. Conservez les erreurs renvoyées. Si ces éléments ne peuvent pas être établis, classez l’appartenance comme inconnue et désignez un responsable du suivi. Ne transformez pas un échec opérationnel en résultat vide obtenu avec succès.

Détection : vérifier le groupe sur un DC choisi

Les exemples PowerShell suivants utilisent une syntaxe documentée par Microsoft Learn. Ce sont des exemples de revue en lecture seule, adaptés avec des valeurs d’environnement fictives, et non des commandes exécutées dans un laboratoire AD pour cet article. Remplacez le serveur, le domaine et l’identité du groupe avant de les exécuter depuis un système disposant du module ActiveDirectory.

Étape 1 : établir l’identité avant de compter les membres

Utilisez un DN, un GUID ou un SID vérifié plutôt que de supposer que le nom d’affichage identifie de façon unique le groupe privilégié recherché. Get-ADGroup prend en charge ces identités et la récupération explicite de propriétés :

$server = 'dc01.example.com'
$groupIdentity = 'CN=Schema Admins,CN=Users,DC=example,DC=com'
$group = Get-ADGroup -Identity $groupIdentity -Server $server -Properties member -ErrorAction Stop
$group | Select-Object DistinguishedName, SID, GroupScope, GroupCategory, member

Pour cet exemple, sélectionnez un DC du domaine racine de la forêt contenant Schema Admins et remplacez le DN en conséquence. Consignez le SID renvoyé et rapprochez-le de l’inventaire de référence des groupes. Si vous examinez plutôt un groupe d’opérateurs, choisissez son identité et son domaine réels. Conservez la fiche d’identité même lorsque la lecture de l’appartenance est vide.

Étape 2 : conserver séparément les résultats directs et récursifs

Get-ADGroupMember accepte un serveur et une identité de groupe explicites. Son mode récursif développe la hiérarchie jusqu’aux membres dépourvus d’objets enfants. Conservez le résultat non récursif pour voir les objets groupes qu’un résultat aplati ne préserve pas :

$direct = @(Get-ADGroupMember -Identity $group.DistinguishedName -Server $server -ErrorAction Stop)
$direct | Select-Object DistinguishedName, objectClass, SID

$recursive = @(Get-ADGroupMember -Identity $group.DistinguishedName -Server $server -Recursive -ErrorAction Stop)
$recursive | Select-Object DistinguishedName, objectClass, SID

Traitez ces résultats comme des ensembles de preuves distincts, et non comme des décomptes interchangeables. Si un résultat direct contient un groupe, examinez l’identité et l’appartenance de ce groupe sur le DC approprié. Un groupe imbriqué vide reste un membre direct de son parent. Une sortie récursive sans comptes ne doit pas effacer cette relation du dossier de revue.

-ErrorAction Stop affiche une erreur et arrête la commande ; il transforme les erreurs non bloquantes en erreurs bloquantes. Si une commande échoue, arrêtez cette mesure et conservez l’erreur ; ne réutilisez pas le contenu d’une variable précédente comme nouveau résultat. Une commande réussie reste une preuve pour le serveur choisi et le périmètre lisible, et non une certification inconditionnelle de tous les domaines ou relations d’approbation. La documentation Microsoft de Get-ADGroupMember exclut également les instantanés Active Directory et les groupes dont des membres se trouvent dans une autre forêt lorsque celle-ci ne dispose pas d’Active Directory Web Service. Consignez chacune de ces limitations comme une lecture non résolue, et non comme un groupe vide.

Étape 3 : lire primaryGroupID lorsque cela s’applique

Pour un groupe de sécurité de domaine vérifié, un contrôle côté comptes peut comparer primaryGroupID au RID de ce groupe. Limitez la requête au domaine représenté par le SID du groupe : le RID seul n’est pas une identité à l’échelle de la forêt. N’appliquez pas mécaniquement cet exemple de groupe de domaine à un SID du conteneur Builtin.

L’exemple suivant utilise les paramètres documentés LDAPFilter, SearchBase, Server et Properties de Get-ADObject, combinés à la définition de primaryGroupID dans le schéma :

$domainBase = 'DC=example,DC=com'
$rid = $group.SID.Value.Split('-')[-1]
$primaryMembers = @(Get-ADObject -LDAPFilter "(primaryGroupID=$rid)" -SearchBase $domainBase -SearchScope Subtree -Server $server -Properties primaryGroupID,objectSid -ErrorAction Stop)
$primaryMembers | Select-Object DistinguishedName, objectClass, objectSid, primaryGroupID

Il s’agit d’une requête de revue, et non d’un script de remédiation du groupe principal. Établissez son applicabilité et la population lisible avant d’interpréter la sortie. Pour les groupes de domaine imbriqués, prenez également en compte les preuves pertinentes côté comptes à ces niveaux ; ne supposez pas que le résultat récursif du niveau supérieur répond à toutes les questions relatives au groupe principal. Si la population ou la visibilité des attributs est incomplète, conservez cette limitation dans la conclusion.

Résoudre les lacunes de preuve avant la clôture (Remediation)

La remédiation consiste ici à lever les incertitudes de la revue ou à documenter la configuration prévue. Les modifications d’appartenance nécessitent une justification distincte. Suivez la séquence ci-dessous après avoir recueilli les preuves d’identité et d’appartenance.

  1. Résoudre les lectures inconnues. Examinez l’erreur consignée, l’identité de collecte, la visibilité des attributs, le périmètre de recherche et les limites d’objets. Lorsque LDAP brut renvoie des attributs d’appartenance par plages, utilisez une méthode de récupération prenant en charge les plages et conservez les preuves de son achèvement. Relancez la lecture concernée sur le DC consigné une fois le problème de collecte résolu.
  2. Rapprocher les membres confirmés. Si la revue native renvoie des membres alors que le collecteur signale une liste vide, conservez les deux sorties avec leurs heures et identités de collecte. Examinez la différence avant de classer le constat. Ne supprimez pas des membres valides pour imposer une concordance avec un export incomplet.
  3. Documenter l’absence intentionnelle de membres. Demandez au responsable du groupe de confirmer sa fonction opérationnelle, l’état vide approuvé et la procédure prévue pour toute utilisation future. Joignez l’identité vérifiée et le périmètre de lecture à cette décision. Pour un groupe d’opérateurs sans membres par défaut, documentez pourquoi l’état actuel correspond au modèle d’administration local.
  4. Faire remonter une absence inattendue de membres. Si le responsable s’attendait à trouver des administrateurs actifs ou un groupe imbriqué documenté, examinez l’écart dans le cadre de la procédure de changement de l’organisation. Ne repeuplez pas automatiquement le groupe à partir d’un ancien export et n’ajoutez pas une identité à large portée comme solution de fortune.
  5. Conserver le dossier de clôture. Incluez le responsable, la décision, la date des preuves, le DC, le SID du groupe, les commandes, les erreurs et les limites non résolues. Définissez les circonstances imposant de réexaminer la décision, comme un changement du modèle d’administration ou une nouvelle divergence dans les preuves collectées.

Le guide associé sur l’appartenance excessive dangereuse aux groupes privilégiés et l’absence intentionnelle de membres dans Schema Admins explique pourquoi remplir un groupe privilégié n’est pas une réponse appropriée à cette Info. Distinguez sa discussion des risques d’accès de la décision sur l’exhaustivité des preuves traitée ici.

Par exemple, une personne chargée de la revue peut recevoir une liste vide du collecteur pour un groupe d’opérateurs. Si l’identité correspond, que les lectures indépendantes se terminent dans le périmètre requis et que le responsable confirme qu’aucun opérateur n’est prévu, la décision peut préserver l’état vide. Si la même revue rencontre une erreur de lecture non résolue, le résultat correct est une appartenance inconnue avec un responsable de suivi désigné. Ce sont des décisions illustratives, et non des résultats de tests observés.

Comment EtcSec détecte ce cas

Le détecteur GROUP_EMPTY_PRIVILEGED d’EtcSec produit un constat Info pour les groupes privilégiés reconnus dont la liste Member collectée satisfait len(Member) == 0. La révision d’etc-collector examinée est 20268a321609c193b79c5da6764f3f56950449cb ; le détecteur se trouve dans public/internal/audit/detectors/ad/groups/privileged/empty-privileged.go.

Il reconnaît dix noms anglais : Domain Admins, Enterprise Admins, Schema Admins, Administrators, Account Operators, Server Operators, Backup Operators, Print Operators, DnsAdmins et Group Policy Creator Owners. Il compare sAMAccountName sans tenir compte de la casse, utilise DisplayName si sAMAccountName est vide, ou recherche une sous-chaîne de nom cn= n’importe où dans le DN. Il ne vérifie ni un SID ni une frontière de RDN. Les groupes renommés ou localisés peuvent être manqués ; une correspondance de nom seule n’établit pas l’identité intégrée.

Le prédicat ne développe pas les appartenances imbriquées et ne calcule pas primaryGroupID. Dans le fournisseur LDAP examiné, la collecte des groupes utilise par défaut (objectClass=group) dans le BaseDN configuré et la limite d’objets. L’analyseur lit exactement member, sans assembler les valeurs member;range=.... L’absence de cet attribut exact devient une liste vide. La pagination des objets ne corrige pas cette lacune de récupération des attributs.

Ces observations du code établissent un risque d’interprétation incomplète, et non un faux positif démontré dans un environnement AD réel. Aucun test AD n’a été exécuté pour cet article. La recommandation générique du détecteur mentionne la suppression des groupes inutilisés ; elle ne doit pas être appliquée aux groupes intégrés. Utilisez l’Info pour déclencher la revue d’identité, d’exhaustivité et de décision du responsable décrite ci-dessus.

Explorez les pages de sécurité des identités liées à ce sujet