Set-Acl Cheatsheet

TL;DR cheatsheet for Set-Acl, used for making changes to ACLs in Windows

Welcome to Part II of our cheatsheet series!

Part I: Mimikatz cheatsheet

Part II: Set-Acl cheatsheet

Part III: Get-Acl cheatsheet

Part IV: Enumerating AD cheatsheet

Background

It’s one command, how complicated can it be right? Well it turned out that this was one of those arcane Windows topics that doesn’t seem to be all over Google and Microsoft made it complicated with GUIDs for both ObjectType and InheritenceObjectType.

However this is a cheatsheet, so let’s get to it with some examples you can copy/paste and very brief explanations of what’s going on in each.

Clone an existing ACL to another AD object

We’ll start with the perhaps most useful of all. If someone gets careless and screws up an ACL you can simply clone a known good one.

$KnownGood = Get-Acl -Path “AD:\ou=user accounts,dc=test,dc=local”
Set-Acl -Path “AD:\ou=VIPs,dc=test,dc=local” -AclObject $KnownGood

A full explanation and example of a screwed up ACL are here.

Grant a given user DCSync [specific] rights

We can add multiple ACEs to an ACL in one go by simply using multiple ‘AddAccessRule’ lines.

If you are removing an ACE then the syntax is exactly the same. Simply substitute ‘$acl.RemoveAccessRule’ and keep the rest the same.

If giving the rights to a group then substitute:

(Get-ADGroup -Identity <group>).SID

The “None” denotes that there is no inheritance being set. We are only setting the root’s ACL.

The two GUIDs specified give insider the exact rights required to DCSync. We could have given them ExtendedRight with all 0s as well, it just wouldn’t be specific.

Handy tables of what the GUIDs mean are linked in the references at the bottom of this cheatsheet.

Import-Module ActiveDirectory
Set-Location AD:
$root = (Get-ADDomain).DistinguishedName
#Add ACL rule for the right “DCSync”
$acl = Get-ACL “$root”
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity Insider).SID
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,”ExtendedRight”,”ALLOW”,([GUID](“1131f6ad-9c07–11d1-f79f-00c04fc2dcd2”)).guid,”None”,([GUID](“00000000–0000–0000–0000–000000000000”)).guid))$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,”ExtendedRight”,”ALLOW”,([GUID](“1131f6aa-9c07–11d1-f79f-00c04fc2dcd2”)).guid,”None”,([GUID](“00000000–0000–0000–0000–000000000000”)).guid))#Apply above ACL rules
Set-ACL “$root” $acl

Confirm:

(Get-Acl $root).Access | Where-Object {($_.IdentityReference -like “*insider*”)}

Change the owner

We can change the owner as well. Bear in mind that the owner has implicit rights to read all and WriteDACL, regardless of what is or isn’t in the ACL itself.

We used this in a lab wherein a malicious insider abused a poorly architected domain to give ownership to a fake Builtin\Administrators group that they controlled.

Import-Module ActiveDirectory
Set-Location AD:
$root = (Get-ADDomain).DistinguishedName
$acl = Get-Acl “$root”
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADGroup -Identity “ꓮdministrators”).SID
$acl.SetOwner($user)
Set-ACL “$root” $acl

Remove a user from all ACEs

This one comes in really handy if an account no longer exists in AD or the AD Recycle Bin. Windows does NOT remove the user from ACLs in this case. They will be listed by SID.

Simply use the OU that the privilege is inherited from in the $root variable. In this case it was applied to the entire domain. It was the old MSOL account AAD Connect uses in case anyone was wondering.

This would also come in rather handy if the previous sysadmin had been really sloppy and overprovisioned a group. Rather than sort through a bunch of ACLs you could just revoke them all, then give that group exactly what rights they need using Set-Acl.

Import-Module ActiveDirectory
Set-Location AD:
#Problem = (Get-Acl “ou=vips,dc=test,dc=local”).Access | Where-Object {$_.IdentityReference -like “*S-1–5–21–4103247791–2828088783–3009141321–3631*”}
#https://ex-shell.com/2017/06/16/remove-a-usergroup-permission-on-an-ad-object-via-powershell/
$root = (Get-ADDomain).DistinguishedName
#$user = “domainjdoe” (to use this substitute $user for $Stale_SID on line 15)
$Stale_SID = “S-1–5–21–4103247791–2828088783–3009141321–3631”
#Collect the current ACL
$Acl = Get-Acl $root
#Loop each access permission in the ACL
ForEach ($access in $acl.Access)
{
if ($access.IdentityReference.Value -eq $Stale_SID)
{
$acl.RemoveAccessRule($access)
}
}
#Set the ACL Back to the AD Object
Set-Acl $root -AclObject $acl

Grant Self with all 0s

This example grants a given user Self with all 0s on a given group. Self with a specific GUID or all 0s gives a user the ability to add or remove themselves from a group.

Import-Module ActiveDirectory
Set-Location AD:
$root = (Get-ADDomain).DistinguishedName
#Give a user Self over a given group
$victim = (Get-ADGroup “Minions” -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity “Mishka”).SID
#Allow Self
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,”Self”,”ALLOW”,([GUID](“00000000–0000–0000–0000–000000000000”)).guid,”None”,([GUID](“00000000–0000–0000–0000–000000000000”)).guid))
#Apply above ACL rules
Set-ACL $victim $acl

Grant Self with specific GUID

The GUID for “self-membership” is bf9679c0–0de6–11d0-a285–00aa003049e2, so to grant only that specific right use:

#Give a user Self over a given group
$victim = (Get-ADGroup “Minions” -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity “Mishka”).SID
#Allow Self
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,”Self”,”ALLOW”,([GUID](“bf9679c0–0de6–11d0-a285–00aa003049e2”)).guid,”None”,([GUID](“00000000–0000–0000–0000–000000000000”)).guid))
#Apply above ACL rules
Set-ACL $victim $acl

Remove rights from a group to an OU

This example removes the ACE granting the group Minions GenericAll on the VIPs OU.

Import-Module ActiveDirectory
Set-Location AD:
$root = (Get-ADDomain).DistinguishedName
#Revoke GenericAll rights from a given group on a given OU
$victim = (Get-ADOrganizationalUnit “ou=vips,$root” -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADGroup -Identity “Minions”).SID
#Allow GenericAll
$acl.RemoveAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,”GenericAll”,”ALLOW”,([GUID](“00000000–0000–0000–0000–000000000000”)).guid,”None”,([GUID](“00000000–0000–0000–0000–000000000000”)).guid))
#Apply above ACL rules
Set-ACL $victim $acl

Inheritance

Lastly, this AD cheatsheet would be incomplete without an example of setting privileges with inheritance. The below gives the Service Desk group the rights to reset passwords and re-enable user accounts only in the OU VIPs.

#Give a group Password reset & re-enable over a given OU
$victim = (Get-ADOrganizationalUnit "ou=VIPs,dc=test,dc=local" -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADGroup -Identity "Service Desk").SID
#Allow specific password reset
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,"ExtendedRight","ALLOW",([GUID]("00299570–246d-11d0-a768–00aa006e0529")).guid,"Descendents",([GUID]("bf967aba-0de6–11d0-a285–00aa003049e2")).guid))
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,"WriteProperty","ALLOW",([GUID]("a8df73f2-c5ea-11d1-bbcb-0080c76670c0")).guid,"Descendents",([GUID]("bf967aba-0de6–11d0-a285–00aa003049e2")).guid))
#Apply above ACL rules
Set-ACL $victim $acl

InheritanceType

InheritanceObjectType

Set NTFS rights

Ironically enough the syntax for NTFS is simpler.

This example grants read to a group.

Set-Location C:
$ACL = Get-Acl -Path “C:\Temp\Share”
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(“Test\Domain Users”,”Read”,”Allow”)
$ACL.SetAccessRule($AccessRule)
$ACL | Set-Acl -Path “C:\Temp\Share”
#Confirm
(Get-Acl -Path “C:\Temp\Share”).Access | Format-Table IdentityReference,FileSystemRights,AccessControlType,IsInherited,InheritanceFlags -AutoSize

Change the owner in NTFS

As with AD, bear in mind that the owner has implicit rights to read all and ChangePermissions, regardless of what is or isn’t in the ACL itself.

#Set the owner in NTFS
$ACL = Get-Acl -Path "C:\Temp"
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADGroup -Identity "Domain Admins").SID
$ACL.SetOwner($user)
$ACL | Set-Acl -Path "C:\Temp"

#Confirm
(Get-Acl "C:\Temp\").Owner

Summary

If this helps anyone else then great. I have been using examples like these in the lab for awhile now. It took me forever to hobble the right syntax together the first time as Set-Acl for AD does not seem to be well known. Once I had examples though it was quick & easy to tweak for different scenarios.

I wanted to put various examples in one cheatsheet since they were spread out over a bunch of different articles.

References

Selfadsi table of GUIDs: http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm

Handy table of GUIDs: https://www.powershellgallery.com/packages/DSACL/1.0.0/Content/DSACL.psm1

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rich

I work various IT jobs & like Windows domain security as a hobby. Most of what’s here is my notes from auditing or the lab.