TL;DR Explanation of Get-ADPermission vs Get-Acl vs dsacls with examples.
Welcome to the annexes of our Auditing AD Series!
Part I: 3 warm up questions to get us started
Part II: Who can reset the CISO’s password?
Part III: Who can execute DCSync?
Part IV: Who can modify the Domain Admins group?
Part V: P0wning a domain in minutes via ACL abuse (why auditing matters)
Part VI: Why Allow statements matter a LOT more than Deny ones
Part VII: Sneaky persistence via hidden objects in AD
Part VIII: SDDL, what is it, does it matter?
Part IX: Do you know who owns your domain?
Part X: Who can push ransomware via Group Policy?
Part XI: Free ways to simplify auditing AD
Part XII: Sidenote on arcane rights like Self
Part XIII: Sidenote on the ScriptPath right
Part XIV: Self & so called “Effective Permissions”
Part XV: Inheritance Explained & an Example
Part XVI: Summary of our Auditing AD Series
Annex A: Scrubbing Group Policy for local admins
Annex B: What Property Sets in AD are, & why they matter
Annex C: Dangerous Rights & RE GUIDs Cheatsheet
Annex D: Mishky’s Blue Team Auditor
Annex E: Even ChatGPT gets this stuff wrong
Annex F: Get-ADPermission Cheatsheet
Annex G: Mishky’s Red Team Enumerate & Attack tools
Background
ChatGPT gave us incomplete information and failed to explain ‘Get-ADPermission’, however with CW6 Google’s help we explored Get-ADPermission and Add-ADPermission in the lab. Get-ADPermission uses similar syntax to Get-Acl, however the output is different. Hence the first thing we did was translate it. Please note that the two don’t show all rights the same, for example ‘Reset Password’ doesn’t show up in Get-ADPermission at all.
This is likely because Add-ADPermission is intended for delegating rights over inboxes and Get-ADPermission is intended for checking the same. However ChatGPT mentioned them and we were curious, so this is what we put together.
+---------------------------------+--------------------------------------+
| Get-Acl | Get-ADPermission |
+---------------------------------+--------------------------------------+
| ActiveDirectoryRights | Access Rights |
| InheritanceType | InheritanceType |
| ObjectType | Properties | |
| InheritedObjectType | InheritedObjectType |
| ObjectFlags | |
| AccessControlType | Deny [True or False] |
| IdentityReference | User |
| IsInherited | IsInherited |
| InheritanceFlags | |
| PropagationFlags | |
| | ChildObjectTypes |
+---------------------------------+--------------------------------------+
Note; Get-ADPermission shows the AD object that the ACE is applied to in the ACE as the ‘Identity’.
It makes more sense with an example. Here are three different ways of showing Organization Management’s rights on Domain Admins:
How to even use Get-ADPermission
ChatGPT left this part out, but to even use this one requires the Exchange Management Shell. Once Exchange is setup one can connect and use this shell via:
#Establish a connection to the Exchange server:
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://TestExchange.test.local/PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $Session -DisableNameChecking
#Once you're done just:
Remove-PSSession $Session
Disconnecting isn’t all that important in a home lab or test environment, but in a large production environment one wouldn’t want to leave too many sessions hanging.
Next we will show some other examples. We will use Set-Acl to grant the right and then show how to check with Get-Acl, Get-ADPermission, and dsacls.
Self
#Give a user Self over a given group
$victim = (Get-ADGroup "Test" -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity "Mishka").SID
#Allow Self with specific GUID
$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
Check via Get-Acl, Get-ADPermission, & dsacls:
#Compare Get-Acl to Get-ADPermission & dsacls using Mishka's Self rights on Test group
(Get-Acl (Get-ADGroup "Test").DistinguishedName).Access | Where-Object {($_.IdentityReference -like "*Mishka*")}
Get-ADPermission (Get-ADGroup "Test").DistinguishedName | Where-Object {($_.User -like "*Mishka*")} | Format-List
dsacls (Get-ADGroup "Test").DistinguishedName | Select-String "Mishka"
Reset Passwords & re-enable user accounts in an OU
#Give a group Password reset & re-enable over a given OU
$victim = (Get-ADOrganizationalUnit "ou=Test,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))
#Allow enabling accounts
$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
Check via Get-Acl, Get-ADPermission, & dsacls:
#Compare Get-Acl to Get-ADPermission & dsacls using Service Desk's rights on Test OU
(Get-Acl (Get-ADOrganizationalUnit "ou=Test,ou=VIPs,dc=test,dc=local").DistinguishedName).Access | Where-Object {($_.IdentityReference -like "*Service Desk*")}
Get-ADPermission (Get-ADOrganizationalUnit "ou=Test,ou=VIPs,dc=test,dc=local").DistinguishedName | Where-Object {($_.User -like "*Service Desk*")} | Format-List
dsacls (Get-ADOrganizationalUnit "ou=Test,ou=VIPs,dc=test,dc=local").DistinguishedName | Select-String "Service Desk"
Check a user account in that OU via Get-Acl, Get-ADPermission, & dsacls:
#Compare Get-Acl to Get-ADPermission & dsacls using Service Desk's rights on Test Dummy Jr
(Get-Acl (Get-ADUser "TestDummy").DistinguishedName).Access | Where-Object {($_.IdentityReference -like "*Service Desk*")}
Get-ADPermission (Get-ADUser "TestDummy").DistinguishedName | Where-Object {($_.User -like "*Service Desk*")} | Format-List
dsacls (Get-ADUser "TestDummy").DistinguishedName | Select-String "Service Desk"
Group Membership Property Set
Let’s try ‘Group Membership’. This includes WriteProperty Member, aka the ability to add & remove users from a group, but is so arcane that even BloodHound missed it.
#Give Mishka Membership rights on Test group
#WriteProperty with ObjectType = BC0AC240–79A9–11D0–9020–00C04FC2D4CF
#Give a user Membership over a given group
$victim = (Get-ADGroup "Test" -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity "Mishka").SID
#Allow WriteProperty with Membership GUID BC0AC240–79A9–11D0–9020–00C04FC2D4CF
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,"WriteProperty","ALLOW",([GUID]("BC0AC240–79A9–11D0–9020–00C04FC2D4CF")).guid,"None",([GUID]("00000000–0000–0000–0000–000000000000")).guid))
#Apply above ACL rules
Set-ACL $victim $acl
Check via Get-Acl, Get-ADPermission, & dsacls:
#Compare Get-Acl to Get-ADPermission & dsacls using Mishka's Self rights on Test group
(Get-Acl (Get-ADGroup "Test").DistinguishedName).Access | Where-Object {($_.IdentityReference -like "*Mishka*")}
Get-ADPermission (Get-ADGroup "Test").DistinguishedName | Where-Object {($_.User -like "*Mishka*")} | Format-List
dsacls (Get-ADGroup "Test").DistinguishedName | Select-String "Mishka"
Add-ADPermission
Even though Add-ADPermission was probably intended for setting rights such as ‘Send As’ or ‘Receive As’, it can be used to delegate other rights over a user account.
Add-ADPermission -Identity “Test Dummy” -User “Mishka” -AccessRights ExtendedRight -ExtendedRights “Send As”
For example we can delegate Mishka the right to set a logon script on another user:
Add-ADPermission -Identity “Test Dummy” -User “Mishka” -AccessRights WriteProperty -Properties ScriptPath
Check:
Get-ADPermission -Identity “Test Dummy” | Where-Object {($_.User -like “*Mishka*”)} | Format-List
Add-ADPermission & Get-ADPermission work pretty well for this, however they start to break down for checking things like Reset Password as we saw earlier. They also don’t work well for delegating rights on a group.
Summary
The Exchange Management Shell is an interesting part of Exchange, and I’m sure we will spend more time with it as we get into M365 and Exchange hybrid. IMHO it is not a replacement for Get-Acl, Set-Acl, and dsacls. As we saw in ‘Ownership Matters’ and ‘Ownership & so called Effective Permissions’ dsacls has it uses to this day.
We didn’t try out enumerating every ‘Dangerous Right’ with Get-ADPermission, however in our sample set of ExtendedRight, Self, and various WriteProperty GUIDs it was too incomplete to use in Mishky’s Red or Blue Team tools. It failed to enumerate the ‘Reset Password’ ExtendedRight, for example, which is a pretty serious shortcoming.
It does do a nice job of resolving GUIDs into commonly understood names for the rights that it does enumerate fully. It is also useful for delegating and checking rights strictly related to Exchange such as ‘Send As’ or ‘Receive As’.
References
Connect remotely to Exchange Management Shell: https://learn.microsoft.com/en-us/powershell/exchange/connect-to-exchange-servers-using-remote-powershell?view=exchange-ps
Control Access Rights, aka ExtendedRight: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1522b774-6464-41a3-87a5-1e5633c3fbbb
Validated Writes, aka Self: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/20504d60-43ec-458f-bc7a-754eb64446df
ScriptPath GUID: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-ada3/c640630e-23ff-44e7-886f-16df9574039e
Property Sets & RE GUIDs: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/177c0db5-fa12-4c31-b75a-473425ce9cca
Rights matched to GUIDs: https://www.powershellgallery.com/packages/DSACL/1.0.0/Content/DSACL.psm1