Hey, Scripting Guy! Can I Determine a Folder’s Access Rights and Who Has Them?

ScriptingGuy1

Share this post:

Hey, Scripting Guy! QuestionHey, Scripting Guy! I am trying to get a handle around the security of a folder on my computer. I need to be able to figure out a way to determine who has access and what those access rights are. I guess I could use the Icacls utility, but I prefer to use something that is native to Windows PowerShell so that I can work with the objects that are returned and not have to waste a bunch of time parsing text.

— BH

Hey, Scripting Guy! AnswerHello BH,

Microsoft Scripting Guy Ed Wilson here. If you have friended me on Facebook, you know that today is my birthday. I am at the point where having a birthday is not necessarily a cause for celebration—the Scripting Wife has not made me a cake and ice cream or invited my friends over for a party. At least not in the last couple of years. But still, I would rather have a birthday than not have a birthday so I am in a good mood. In addition, with the Scripting Wife, one never knows what she may have up her sleeve for the occasion.

Back to your question. If you do not want to use the Icacls utility because it is not native to Windows PowerShell, the best tool to use to work with security on a folder is the Windows PowerShell Get-Acl cmdlet. When you use the Get-Acl cmdlet and give it the path to a folder, it returns an instance of the System.Security.AccessControl.DirectorySecurity object, which is documented on MSDN and is used to represent the access control and the audit security for a directory. It specifies the access rights for a directory and how access attempts are audited. The class represents each of the access and audit rights as a set of rules. The access rules are presented as instances of the System.Security.AccessControl.FileSystemAccessRule object and the audit rules are presented as instances of the System.Security.AccessControl.FileSystemAuditRule class.  

To retrieve the DirectorySecurity object using the Get-Acl cmdlet, you specify the path to the folder via the path parameter. This is seen here:

PS C:\> Get-Acl -Path C:\fso

    Directory: C:\

Path                       Owner                      Access
—-                       —–                      ——
fso                        BUILTIN\Administrators     NWTRADERS\Administrato…

PS C:\>

You can see from the output that the Owner property is returned. The Access property is truncated and does not display all of the users who have access to the folder. You might decide to pipe the results to the Select-Object cmdlet and choose the Access property. When you use this technique, as seen here, the Access control information is still truncated:

PS C:\> Get-Acl -Path C:\fso | select-object access

Access
——
{System.Security.AccessControl.FileSystemAccessRule, System.Security.AccessC…

PS C:\>

If you pipe the result of the Select-Object cmdlet to the Format-List cmdlet and choose all of the properties, you will finally be able to see all of the information returned from the Access property. As seen here, however, the results are not what might be expected:

PS C:\> Get-Acl -Path C:\fso | select-object access | Format-List *

Access : {System.Security.AccessControl.FileSystemAccessRule, System.Security.A
         ccessControl.FileSystemAccessRule, System.Security.AccessControl.FileS
         ystemAccessRule, System.Security.AccessControl.FileSystemAccessRule…
         }

PS C:\>

To retrieve a list of the users who have access to the folder, you need to use the accessToString property because the access rights to the folder is stored as a series of FileSystemAccessRules. After you have piped the results to the Format-List cmdlet, you no longer have a DirectorySecurity object. You have a formatted textual representation of the underlying object. This is seen here:

PS C:\> Get-Acl -Path C:\fso | Format-List AccessToString

AccessToString : NWTRADERS\Administrator Allow  FullControl
                 BUILTIN\Administrators Allow  FullControl
                 BUILTIN\Administrators Allow  268435456
                 NT AUTHORITY\SYSTEM Allow  FullControl
                 NT AUTHORITY\SYSTEM Allow  268435456
                 BUILTIN\Users Allow  ReadAndExecute, Synchronize
                 NT AUTHORITY\Authenticated Users Allow  Modify, Synchronize
                 NT AUTHORITY\Authenticated Users Allow  -536805376

If you wish to write to a text file the list of people who have access to the folder, the above formatted list is quite acceptable. To write the users who have access to a text file, you can use the Out-File cmdlet as seen here:

PS C:\> Get-Acl -Path C:\fso | Format-List accessToString |
Out-File -FilePath c:\fso\fsoAcl.txt -Append
PS C:\>

When the above command is run, the following text file is seen:

Image of text file displayed when command is run

If you prefer to work with the folder in a more direct manner, you can use the Get-Acl cmdlet to retrieve the DirectorySecurity object, and you can store it in a variable. This is seen here:

PS C:\> $acl = Get-Acl -Path C:\fso
PS C:\> $acl

    Directory: C:\

Path                       Owner                      Access
—-                       —–                      ——
fso                        BUILTIN\Administrators     NWTRADERS\Administrato…

PS C:\>

After you have the DirectorySecurity object stored in a variable, you can work directly with the underlying objects. This is shown here:

PS C:\> $acl = Get-Acl -Path C:\fso
PS C:\> $acl

    Directory: C:\

Path                       Owner                      Access
—-                       —–                      ——
fso                        BUILTIN\Administrators     NWTRADERS\Administrato…

To examine the methods and properties that are available from the object we have stored in the $acl variable, we use the Get-Member cmdlet. This is seen here:

PS C:\> $acl | Get-Member

   TypeName: System.Security.AccessControl.DirectorySecurity

Name                            MemberType     Definition
—-                            ———-     ———-
Access                          CodeProperty   System.Security.AccessControl…
Group                           CodeProperty   System.String Group{get=GetGr…
Owner                           CodeProperty   System.String Owner{get=GetOw…
Path                            CodeProperty   System.String Path{get=GetPath;}
Sddl                            CodeProperty   System.String Sddl{get=GetSddl;}
AccessRuleFactory               Method         System.Security.AccessControl…
AddAccessRule                   Method         System.Void AddAccessRule(Sys…
AddAuditRule                    Method         System.Void AddAuditRule(Syst…
AuditRuleFactory                Method         System.Security.AccessControl…
Equals                          Method         bool Equals(System.Object obj)
GetAccessRules                  Method         System.Security.AccessControl…
GetAuditRules                   Method         System.Security.AccessControl…
GetGroup                        Method         System.Security.Principal.Ide…
GetHashCode                     Method         int GetHashCode()
GetOwner                        Method         System.Security.Principal.Ide…
GetSecurityDescriptorBinaryForm Method         byte[] GetSecurityDescriptorB…
GetSecurityDescriptorSddlForm   Method         string GetSecurityDescriptorS…
GetType                         Method         type GetType()
ModifyAccessRule                Method         bool ModifyAccessRule(System….
ModifyAuditRule                 Method         bool ModifyAuditRule(System.S…
PurgeAccessRules                Method         System.Void PurgeAccessRules(…
PurgeAuditRules                 Method         System.Void PurgeAuditRules(S…
RemoveAccessRule                Method         bool RemoveAccessRule(System….
RemoveAccessRuleAll             Method         System.Void RemoveAccessRuleA…
RemoveAccessRuleSpecific        Method         System.Void RemoveAccessRuleS…
RemoveAuditRule                 Method         bool RemoveAuditRule(System.S…
RemoveAuditRuleAll              Method         System.Void RemoveAuditRuleAl…
RemoveAuditRuleSpecific         Method         System.Void RemoveAuditRuleSp…
ResetAccessRule                 Method         System.Void ResetAccessRule(S…
SetAccessRule                   Method         System.Void SetAccessRule(Sys…
SetAccessRuleProtection         Method         System.Void SetAccessRuleProt…
SetAuditRule                    Method         System.Void SetAuditRule(Syst…
SetAuditRuleProtection          Method         System.Void SetAuditRuleProte…
SetGroup                        Method         System.Void SetGroup(System.S…
SetOwner                        Method         System.Void SetOwner(System.S…
SetSecurityDescriptorBinaryForm Method         System.Void SetSecurityDescri…
SetSecurityDescriptorSddlForm   Method         System.Void SetSecurityDescri…
ToString                        Method         string ToString()
PSChildName                     NoteProperty   System.String PSChildName=fso
PSDrive                         NoteProperty   System.Management.Automation….
PSParentPath                    NoteProperty   System.String PSParentPath=Mi…
PSPath                          NoteProperty   System.String PSPath=Microsof…
PSProvider                      NoteProperty   System.Management.Automation….
AccessRightType                 Property       System.Type AccessRightType {…
AccessRuleType                  Property       System.Type AccessRuleType {g…
AreAccessRulesCanonical         Property       System.Boolean AreAccessRules…
AreAccessRulesProtected         Property       System.Boolean AreAccessRules…
AreAuditRulesCanonical          Property       System.Boolean AreAuditRulesC…
AreAuditRulesProtected          Property       System.Boolean AreAuditRulesP…
AuditRuleType                   Property       System.Type AuditRuleType {get;}
AccessToString                  ScriptProperty System.Object AccessToString …
AuditToString                   ScriptProperty System.Object AuditToString {…

The Access property is a codeproperty. This means it was added by the Windows PowerShell team. To see what you can do with the Access property, pipe it to the Get-Member cmdlet. This is seen here:

PS C:\> $acl.Access | Get-Member

   TypeName: System.Security.AccessControl.FileSystemAccessRule

Name              MemberType Definition
—-              ———- ———-
Equals            Method     bool Equals(System.Object obj)
GetHashCode       Method     int GetHashCode()
GetType           Method     type GetType()
ToString          Method     string ToString()
AccessControlType Property   System.Security.AccessControl.AccessControlType…
FileSystemRights  Property   System.Security.AccessControl.FileSystemRights …
IdentityReference Property   System.Security.Principal.IdentityReference Ide…
InheritanceFlags  Property   System.Security.AccessControl.InheritanceFlags …
IsInherited       Property   System.Boolean IsInherited {get;}
PropagationFlags  Property   System.Security.AccessControl.PropagationFlags …

PS C:\>

The Access property returns an instance of the System.Security.AccessControl.FileSystemAccessRule .NET Framework class. When you look at the Access property, it displays the following information:

PS C:\> $acl.Access

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : NWTRADERS\Administrator
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : True
InheritanceFlags  : None
PropagationFlags  : None

FileSystemRights  : 268435456
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : True
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : InheritOnly

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited       : True
InheritanceFlags  : None
PropagationFlags  : None

FileSystemRights  : 268435456
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited       : True
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : InheritOnly

FileSystemRights  : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : BUILTIN\Users
IsInherited       : True
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : Modify, Synchronize
AccessControlType : Allow
IdentityReference : NT AUTHORITY\Authenticated Users
IsInherited       : True
InheritanceFlags  : None
PropagationFlags  : None

FileSystemRights  : -536805376
AccessControlType : Allow
IdentityReference : NT AUTHORITY\Authenticated Users
IsInherited       : True
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : InheritOnly

 

Because the System.Security.AccessControl.FileSystemAuditRule class is returned as a collection, you can index directly into it. This is seen here:

PS C:\> $acl.Access[0]

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : NWTRADERS\Administrator
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

The IdentityReference property returns an instance of System.Security.Principal.NTAccount .NET Framework class. The members of this object are seen here:

PS C:\> $acl.Access[0].identityReference | Get-Member

   TypeName: System.Security.Principal.NTAccount

Name              MemberType Definition
—-              ———- ———-
Equals            Method     bool Equals(System.Object o)
GetHashCode       Method     int GetHashCode()
GetType           Method     type GetType()
IsValidTargetType Method     bool IsValidTargetType(type targetType)
ToString          Method     string ToString()
Translate         Method     System.Security.Principal.IdentityReference Tra…
Value             Property   System.String Value {get;}

The IdentityReference property points to a specific user account. You can use that property to return a list of all the users who have access to a folder. When you query the Value property, it returns a string. This is seen here:

PS C:\> $acl.Access | ForEach-Object { $_.identityReference.value }
NWTRADERS\Administrator
BUILTIN\Administrators
BUILTIN\Administrators
NT AUTHORITY\SYSTEM
NT AUTHORITY\SYSTEM
BUILTIN\Users
NT AUTHORITY\Authenticated Users
NT AUTHORITY\Authenticated Users
PS C:\>

If you wanted to search the list of users for a specific user who has rights, you could pipe the results to the Where-Object. This is seen here:

PS C:\> $acl.Access | ForEach-Object { $_.identityReference.value |
Where-Object { $_ -eq ‘nwtraders\administrator’ }  }
NWTRADERS\Administrator
PS C:\>

Well, BH, this brings us to the end of another Hey, Scripting Guy! post. We hope we have inspired you to fire up Windows PowerShell and start playing around with the Get-Acl cmdlet.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

0 comments

Discussion is closed.

Feedback usabilla icon