Changing NTFS Security Permissions using PowerShell

Overview

Changing NTFS permissions with PowerShell saves a lot of time when you need to make changes to a large group of files or when it is required as part of a larger automation project. This article should help you understand everything you need to know to manipulate security permissions with PowerShell.

When changing ownership of files or folders you must run PowerShell as an Administrator. Everything here will work in Windows PowerShell 5, but not PowerShell 6 as of this writing – specifically, the SetAccessControl() method does not exist in PowerShell 6.

Viewing ACL

We are going to use the Get-Acl cmdlet to view the current ACL. Running it in PowerShell will give the following output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
PS C:\Users\larntz\Documents> Get-Acl .\Directory\ | Format-List


Path   : Microsoft.PowerShell.Core\FileSystem::C:\Users\Administrator\Documents\Directory\
Owner  : WIN-UBFNHEQ8GII\Administrator
Group  : WIN-UBFNHEQ8GII\None
Access : NT AUTHORITY\SYSTEM Allow  FullControl
         BUILTIN\Administrators Allow  FullControl
         WIN-UBFNHEQ8GII\Administrator Allow  FullControl
Audit  :
Sddl   : O:LAG:S-1-5-21-3514988389-1168544693-1271638760-513D:AI(A;OICIID;FA;;;SY)(A;OICIID;FA;;;BA)(A;OICIID;FA;;;LA)

Our primary focus in this article will be on the Owner and Access objects. We can see from this example that WIN-UBFNHEQ8GII\Administrator is the owner and we have three Access rules granting FullControl.

Ownership Details

Ownership is pretty simple. Ownership is assigned to one user or group and there are no additional details.

1
2
PS C:\Users\larntz\Documents> (Get-Acl .\Directory\).Owner
WIN-UBFNHEQ8GII\Administrator

Access Right Details

We can see a more detailed description of the access rules by selecting them specifically using this command (Get-Acl .\Directory\).Access. Now we can see which permissions were inherited and the InheritanceFlags and PropagationFlags. These latter two will be important when we start modifying rules.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PS C:\Users\larntz\Documents> (Get-Acl .\Directory\).Access


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

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

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : WIN-UBFNHEQ8GII\Administrator
IsInherited       : True
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

Modifying ACL

Before we can set an object’s ACL we need to build one. The easiest way to do that is to save the current ACL in a variable and then modify it. To do that we’ll just assing the output of Get-Acl to $acl.

1
PS C:\Users\larntz\Documents> $acl = Get-Acl .\Directory\

Another option would be to create a completely new, and empty, ACL object like this:

1
PS C:\Users\larntz\Documents> $acl = New-Object System.Security.AccessControl.DirectorySecurity

Now that we have our ACl object we can make modifications. Once we’ve made the desired changes we have to apply it back to the directory or our changes will be lost.

Setting Ownership

Setting the owner in the ACL is almost as simple as viewing it. We will use the SetOwner() method on the ACL. This method takes one argument of type System.Security.Principal.NTAccount so first we need to create an object of that type and then we can set the owner.

However, there are two limitations when setting ownership via PowerShell.

  1. We need to be running powershell as Administrator.
  2. We can only set the owner to the user currently running PowerShell or BUILTIN\Administrators.
1
2
PS C:\Users\larntz\Documents> $owner = New-Object System.Security.Principal.NTAccount("BUILTIN\Administrators")
PS C:\Users\larntz\Documents> $acl.SetOwner($owner)

Remember, we haven’t changed anything on the filesystem yet. We’ve only modified our $acl object.

Inheritance Flags

When creating access rules we will want to specify inheritance flags also. When doing so we have four options. You will most likely want to set both the ContainerInheritance and the ObjectInheritance flags. This indicates that we want our permission to be propagated to all child directories and files.

Inheritance Flag Meaning
ContainerInherit Propagate to child containers (directories).
None Do not propagate this permission to any child containers or objects.
ObjectInherit Propagate to child objects (files).

Propagation Flags

In addtion to Inheritance Flags we can also set Propagation Flags. The default Windows behavior is None. See the table below for more detail on the three Propagation Flag options. Setting this flag to InheritOnly will cause the access rule to only apply to child objects of the container.

Propagation Flag Meaning
InheritOnly Specifies that the ACE is propagated only to child objects. This includes both container and leaf child objects.
None Specifies that no inheritance flags are set.
NoPropagateInherit Specifies that the ACE is not propagated to child objects.

Flag Combinations and Effect

The table below details how a rule will be apply to the current object and child objects based on the flags set in the access rule.

Access Rule Applies To Inheritance Flags Propagation Flags
Subfolders and Files only ContainerInherit,ObjectInherit InheritOnly
This Folder, Subfolders and Files ContainerInherit,ObjectInherit None
This Folder, Subfolders and Files ContainerInherit,ObjectInherit NoPropagateInherit
This folder and Subfolders ContainerInherit None
Subfolders only ContainerInherit InheritOnly
This Folder and Files ObjectInherit None
This Folder and Files ObjectInherit NoPropagateInherit

Access Control Types

There are only two access control types. Allow and Deny. Allow means we are allowing the permission, e.g., we are allowing a user to write to this directly. Deny will specifically deny a right, and takes precedence over Allow permissions. So, if a user has a Modify/Allow entry and also a Read/Deny that user will have all Modify rights except read.

Be sure to verify a principal’s effective access when using Deny types.

Basic Permissions

When we talk about basic permissions we are talking about the primary checkboxes available when looking at the security tab in a file system object’s Properties dialog.

Basic Permissions

Here is a table of basic permissions that can be set via PowerShell, and the rights each will grant.

Permission Rights Granted
FullControl Specifies the right to exert full control over a folder or file, and to modify access control and audit rules. This value represents the right to do anything with a file and is the combination of all rights in this enumeration.
Modify Specifies the right to read, write, list folder contents, delete folders and files, and run application files. This right includes the ReadAndExecute right, the Write right, and the Delete right.
ReadAndExecute Specifies the right to open and copy folders or files as read-only, and to run application files. This right includes the Read right and the ExecuteFile right.
Read Specifies the right to open and copy folders or files as read-only. This right includes the ReadData right, ReadExtendedAttributes right, ReadAttributesright, and ReadPermissions right.
Write Specifies the right to create folders and files, and to add or remove data from files. This right includes the WriteData right, AppendData right, WriteExtendedAttributes right, and WriteAttributes right.

Note that List folder contents is not in the table above. While this can be set via PowerShell it will show up under Special permissions as List folder / read data.

Adding Basic Permissions

To add new rights to a folder we will need to first create a file system rule, and then we can add it to our current set of $acl. There are two methods we can use to either add or set a rule.

SetAccessRule() vs AddAccessRule()

The first method is SetAccessRule(). When using SetAccessRule() our new rule will overwrite any existing rule of the same type (Allow or Deny) for that security principal (user or group) regardless of the existing permissions. If a user has Modify permission and a new rule is created using SetAccessRule() specifying Read permission that user will now only have Read permission. This method essentially removes any existing access an replaces that access with the specified rule.

The second method is AddAccessRule(). This method will add this access rule to the ACL. Here if a user has Modify permission and we use AddAccessRule() to create a new rule with Read permission the user will still have Modify permissions. This can be dangerous from a security perspective if we think we intend to limit a user’s access, but mistakenly use the AddAccessRule() method.

My suggestion is always use SetAccessRule() and specify all intended permissions when making ACL changes.

Creating A New FileSystem Access Rule

Now that we understand inheritance flags, basic permissions, and the methods used to add a rule to our $acl we are ready to create a new filesystem rule. This is a two step process. First we create our rule, and then we will apply it to our $acl object.

Here’s what we need to create the rule.

1
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("DOMAIN\larntz","Write","ContainerInherit,ObjectInherit","None","Allow")

The code block above creates a new object of type System.Security.AccessControl.FileSystemAccessRule with the following parameters:

Parameter Value
identity DOMAIN\larntz
fileSystemRights Write
inheritanceFlags ContainerInherit,ObjectInherit
propagationFlags None
type Allow

After creating the rule we can apply it to our $acl object using the SetAccessRule() method.

1
$acl.SetAccessRule($rule)

Again, we haven’t modified the filesystem yet. We’ve only modified our $acl object. Next let’s look at how to apply our $acl object to a filesystem object.

Removing A FileSystem Access Rule

To remove an existing access rule you should use the RemoveAccessRule() method. This is very straightfoward once you understand how to create an access rule. To remove a rule it must already be part of the $acl object. Generally you would loop through these to find the rule you wanted and assign it to a variable. Then you can call $acl.RemoveAccessRule($rule) to remove the rule from the $acl object.

Here is a simple example to illustrate. This example demonstrates create an ACL object, create a rule, listing the access rules in our ACL object, and then removing the access rule from the ACL object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
PS C:\Users\larntz\Documents> $acl = New-Object System.Security.AccessControl.DirectorySecurity
PS C:\Users\larntz\Documents> $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("DOMAIN\larntz","Read,CreateFiles","ContainerInherit,ObjectInherit","None","Allow")
PS C:\Users\larntz\Documents> $acl.SetAccessRule($rule)
PS C:\Users\larntz\Documents> $acl.Access


FileSystemRights  : CreateFiles, Read, Synchronize
AccessControlType : Allow
IdentityReference : DOMAIN\larntz
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None


PS C:\Users\larntz\Documents> $acl.RemoveAccessRule($rule)
True
PS C:\Users\larntz\Documents> $acl.Access
PS C:\Users\larntz\Documents>

Saving the ACL Changes

To avoid a bug in Set-Acl we will be using the SetAccessControl() method to save our permissions. If we need to be compatible with PowerShell 6 we must use Set-Acl, but you may experience odd behavior after using it and from personal experience I don’t recommend using Set-Acl.

What we are going to do instead is use the SetAccessControl() method of the DirectoryInfo class to apply our ACL.

To do this we can use Get-Item and then call SetAccessControl() on the returned object.

1
(Get-Item .\Directory\ChildDirectory\).SetAccessControl($acl)

Putting all the steps together we can get or create an ACL object, add a rule, and apply that rule to a file system object. The code block below shows all three steps together.

1
2
3
PS C:\Users\larntz\Documents> $acl = Get-Acl .\Directory\
PS C:\Users\larntz\Documents> $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("DOMAIN\larntz","Write","ContainerInherit,ObjectInherit","None","Allow")
PS C:\Users\larntz\Documents> $acl.SetAccessRule($rule)

Special Permissions

A basic right such as Modify can be thought of as a group of special permissions. Special permissions are more detailed rights that can be assigned rather than using the pre-defined basic rights groups. For instance, if you want to allow a principal to create files, but not directories that can be accomplished using special rights. These type permissions are only viewable in the GUI via the Advanced button on the Security tab.

Special Permissions

At first, it may take some experimentation to get the desired rights when dealing with advanced permissions. Be sure to test these settings thoroughly to be sure everything behaves as intended.

Now, using the example above let’s grant a user Read and CreateFiles permission only. This will allow a user to read the directory tree and files, but only allow them to paste new files into the folders. As you can see in the table below the CreateFiles permission does not grant AppendData which is needed to change data in an existing file. Also, once the user creates/moves a file into this directory they will be unable to delete it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
PS C:\Users\larntz\Documents> $acl = get-acl .\Directory\
PS C:\Users\larntz\Documents> $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("DOMAIN\larntz","Read,CreateFiles","ContainerInherit,ObjectInherit","None","Allow")
PS C:\Users\larntz\Documents> $acl.SetAccessRule($rule)
PS C:\Users\larntz\Documents> (Get-Item .\Directory\).SetAccessControl($acl)
PS C:\Users\larntz\Documents> (Get-Acl .\Directory\).Access


FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : CreateFiles, Read, Synchronize
AccessControlType : Allow
IdentityReference : DOMAIN\larntz
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

Table of Special Permissions

Permission Rights Granted
AppendData Specifies the right to append data to the end of a file.
ChangePermissions Specifies the right to change the security and audit rules associated with a file or folder.
CreateDirectories Specifies the right to create a folder.
CreateFiles Specifies the right to create a file.
Delete Specifies the right to delete a folder or file.
DeleteSubdirectoriesAndFiles Specifies the right to delete a folder and any files contained within that folder.
ExecuteFile Specifies the right to run an application file.
ListDirectory Specifies the right to read the contents of a directory.
ReadAttributes Specifies the right to open and copy file system attributes from a folder or file. For example, this value specifies the right to view the file creation or modified date. This does not include the right to read data, extended file system attributes, or access and audit rules.
ReadData Specifies the right to open and copy a file or folder. This does not include the right to read file system attributes, extended file system attributes, or access and audit rules.
ReadExtendedAttributes Specifies the right to open and copy extended file system attributes from a folder or file. For example, this value specifies the right to view author and content information. This does not include the right to read data, file system attributes, or access and audit rules.
ReadPermissions Specifies the right to open and copy access and audit rules from a folder or file. This does not include the right to read data, file system attributes, and extended file system attributes.
Synchronize Specifies whether the application can wait for a file handle to synchronize with the completion of an I/O operation.
TakeOwnership Specifies the right to change the owner of a folder or file. Note that owners of a resource have full access to that resource.
Traverse Specifies the right to list the contents of a folder and to run applications contained within that folder.
WriteAttributes Specifies the right to open and write file system attributes to a folder or file. This does not include the ability to write data, extended attributes, or access and audit rules.
WriteData Specifies the right to open and write to a file or folder. This does not include the right to open and write file system attributes, extended file system attributes, or access and audit rules.
WriteExtendedAttributes Specifies the right to open and write extended file system attributes to a folder or file. This does not include the ability to write data, attributes, or access and audit rules.

Conclusion

That covers the building blocks of modifying NTFS permissions with powershell. I would love feed back so please feel free to send questions, corrections, or general comments about the article to larntz+ntfssecposh@gmail.com.

References

Microsoft Docs

Related Content