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
Part V: Windows reverse shells cheatsheet
Part VI: MS Graph PowerShell cheatsheet
Part VII: Hash cracking cheatsheet
Part VIII: The Credential Theft Shuffle
Part IX: SACLs & Querying Collected Logs
Part X: Setting up a simple AD lab in Azure
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.
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
Please note that if the AD ACL is completely FUBARed than a Domain Admin will have to either use a GUI tool like ADUC or dsacls to seize ownership.
dsacls “ou=vips,dc=test,dc=local” /takeownership
Once ownership has been seized they can then fix the ACL itself by using the clone method shown earlier.
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 users in 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 ExtendedRight on GUID for 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))
#Allow specific WriteProperty on GUID for Enabled
$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
If the NTFS ACL is completely FUBARed then a local admin on the server can seize ownership in the GUI or with the CLI tool takeown.
takeown /R /A /F Temp /D N
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
icacls: https://ss64.com/nt/icacls.html
takeown: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/takeown