Répertoires DFS visibles sans autorisation d'accès

J'ai été confronté à un problème provenant de la bureautique. Des utilisateurs voyaient dans leur liste de répertoires partagés sous Windows des partages DFS auxquels ils n'avaient pas accès, en plus de leurs répertoires DFS usuels. Normalement, Windows n'affiche pas de répertoire partagé si l'utilisateur n'a pas d'accès en lecture. Par exemple, si l'on considère la racine \\dundermifflin.inc\ et 3 répertoires DFS Sales, Accounting et Boss, si l'utilisateur n'a accès qu'au dernier il ne peut pas voir les dossiers Sales et Accounting.

Or dans mon cas, ces répertoires étaient bien visibles. La cause provient de la manière dont les permissions ont été positionnées dans la console DFS. Lors de la création d'un répertoire DFS, il est possible de positionner les privilèges de deux manières : en utilisant soit les permissions NTFS, soit DFS.

En choisissant l'option Use inherited permissions from the local file system, Windows ne va pas appliquer de permissions DFS sur le répertoire. Ainsi, comme son nom l'indique, les droits seront les mêmes que ceux positionnés sur le serveur qui héberge le répertoire en question. C'est justement ce réglage qui déclenche l'affichage dans l'explorateur. N'ayant aucune permission DFS de configurée, Windows ne sait pas avant d'interroger le serveur qui porte le répertoire si l'utilisateur a le droit de se connecter au non ; le répertoire est donc affiché. Ce n'est que lorsque l'utilisateur tente d'y accéder que Windows va récupérer les ACL et empêcher l'accès. Le comportement est par ailleurs expliqué dans la fenêtre ci-dessus.

La deuxième option, Set explicit view permissions on the DFS folder, place donc des permissions DFS directement sur le lien DFS (traduction de \\FileServer03.dundermifflin.inc\Shares vers \\dundermifflin.inc\shares). Ainsi, dès l'ouverture de l'explorateur, Windows lit ces ACL et n'affiche pas le répertoire puisqu'il sait que l'utilisateur n'y a pas accès.

Ce script Powershell permet d'afficher les répertoires DFS qui sont configurés avec la première option et qui apparaissent dans l'explorateur, si jamais vous souhaitez faire une passe complète sur tous vos shares DFS afin d'adopter une configuration homogène :

Param([Parameter(Mandatory=$true)][string] $Namespace)
$fNameSpace = "$Namespace\*"
Get-DfsnFolder $fNameSpace | where-object { (Get-DfsnAccess $_.Path) -eq $null }

Il suffit de l'appeler de cette manière :

.\DFS-NoPerm.ps1 -Namespace \\dundermifflin.inc\shares

Octroi de droits à un compte sur un service grâce à subinacl

En recherchant un moyen d'accorder les droits de démarrage / arrêt sur un service particulier pour un compte d'utilisateur standard, je suis tombé sur cet article sur Serverfault. Le but était d'éviter d'accorder des privilèges d'administration à l'utilisateur en question.

Il existe donc un outil nommé SubInACL, qui fait partie du Windows Resource Kit (aux côtés de nombreux autres outils que je connaissais comme LockOutStatus). Cet outil qui s'exécute en ligne de commande permet de choisir précisément quels privilèges accorder sur un service pour un utilisateur, qu'il soit local ou du domaine.

J'ai testé cet outil sur un serveur de test en 2008 R2 et appliqué le fonctionnement sur un 2016 ; son exécution est très simple. Microsoft explique toute la syntaxe disponible à ce lien. Si je souhaite accorder à l'utilisateur dschrute le droit de voir l'état et de relancer le service NTP, je vais devoir envoyer cette instruction :

subinacl.exe /service w32time /GRANT=DUNDERMIFFLIN\dschrute=STO

Voici sur un Server 2016, le résultat de la commande pour le service Windows Update :

Si SubInACL n'est plus disponible sur le site de Microsoft, il est disponible en téléchargement sur le miroir du blog à ce lien.

Utilisation de Get-ACL sur une arborescence ActiveDirectory

Cet article fait plus ou moins écho à celui d'hier où j'explique comment accorder des droits spécifiques à un utilisateur ou un groupe sur une OU ActiveDirectory. Get-ACL est une instruction Powershell permettant de retourner les permissions d'un fichier, répertoire ou même clef de registre. Par défaut, Get-ACL ne permet pas de retourner les autorisations d'un objet ActiveDirectory, mais il existe une technique de sioux permettant d'utiliser cette instruction sur un AD.

Sur une station ayant les RSAT d'installés ou bien directement sur un contrôleur de domaine, il suffit d'importer le module AD pour Powershell :

Import-Module ActiveDirectory

Ensuite, se placer dans l'arborescence AD :

Set-Location AD:

Un simple dir permet de retourner des informations nous confirmant que nous sommes bien dans l'AD.

Lancer un Get-ACL à la racine de AD: n'aura aucun effet. Il est tout de même nécessaire d'indiquer un chemin à la commande ; on utilisera alors le DistingushedName. Par exemple, pour récupérer l'intégralité des permissions à la racine du domaine (attention, ce n'est pas récursif !) :

(Get-Acl (Get-ADDomain).DistinguishedName).Access

Ainsi, il est possible de se concocter un petit snippet si l'on souhaite parcourir tout l'AD à la recherche de privilèges accordés à un groupe ou à un utilisateur sur des OU, par exemple :

Import-Module ActiveDirectory
Set-Location AD:
$oulist = Get-ADOrganizationalUnit -Filter * | select DistinguishedName
foreach($ou in $oulist){
$privileges = (Get-Acl $ou.DistinguishedName).Access | Where-Object { $_.IdentityReference -eq "DUNDERMIFFLIN\gclooney" }
if($privileges -ne $null) { Write-Host "OU:"$ou.DistinguishedName ; $privileges }
}

Par exemple, ayant accordé les droits à l'utilisateur gclooney sur l'OU End-Users, il récupère par héritage ces mêmes privilèges sur les 3 OU enfant.

Cela se vérifie avec le snippet plus haut :

Ce code peut naturellement être modifié pour interroger des groupes ou des utilisateurs. Par exemple, je vais octroyer des droits au groupe US-Presidents sur le groupe Actors. La capture suivante montre bien que le droit WriteProperty a été attribué.

En jouant sur la clause Where-Object de ce snippet, on peut modifier le filtre de recherche. Par exemple, afin rechercher tous les utilisateurs ayant le droit WriteProperty sur un objet défini, il suffit de modifier le snippet :

$grplist = Get-ADgroup -Identity "Actors" | select DistinguishedName
$privileges = (Get-Acl $grp.DistinguishedName).Access | Where-Object { $_.ActiveDirectoryRights -like "*WriteProperty*" }

Au final, la seule limite de Get-Acl et du code que l'on adapte autour, ce sont les informations que l'on souhaite récupérer et les actions éventuelles à mener pour cadrer au mieux les privilèges attribués au fil du temps !

Octroi de droits à un utilisateur spécifique sur une OU

Récemment, j'ai dû implémenter une tâche planifiée exécutant des scripts Powershell - vulgairement appelés moulinettes - de manière assez régulière pour automatiser et palier à de possibles oublis humains. Cette tâche s'exécute avec un compte de service ; seulement ce compte de service doit pouvoir modifier des groupes ActiveDirectory. Par défaut, un compte fraîchement créé ne dispose pas de tels privilèges. Il a donc fallu que j'accorde les droits à ce compte de service pour qu'il puisse écrire sur les objets présents dans une OU spécifique. A noter que la procédure ci-dessous - quasi-similaire à l'octroi de droits sur un répertoire NTFS tout simple - fonctionne pour la très grande majorité des objets ActiveDirectory.

La console ActiveDirectory, pouvant s'appeler avec dsa.msc doit avoir les fonctionnalités avancées d'activées : View > Advanced Features.

Ensuite, se rendre sur l'OU en question, puis ouvrir les propriétés de celle-ci. Les fonctionnalités avancées débloquent l'onglet Security. Cet onglet affiche les entités ayant des privilèges particuliers sur l'OU. En cliquant sur Advanced, une fenêtre apparaît.

Les diverses autorisations ou interdictions sont listées ; il est possible de faire un test avec un compte d'utilisateur dans Effective Access pour vérifier que ce dernier a bien le droit - ou non - d'effectuer certaines opérations sur cette OU.

Add ouvre une nouvelle fenêtre qui demandera de saisir un compte ; je vais donc saisir mon compte de service, puis lui accorder le privilège d'écriture (encadré en bleu).

Par défaut, le compte de service a le droit de lire les propriétés de l'OU ainsi que la parcourir. En ajoutant le droit d'écriture, j'autorise le compte à modifier les objets présents dans l'OU car l'octroi concerne cette OU et ce qu'elle contient (paramètre encadré en vert).

Une simple exécution de test de la tâche planifiée a confirmé le bon fonctionnement de l'accord des privilèges.