Self and so called “Effective Permissions”

Rich
7 min readJan 1, 2023

--

TL;DR It turns out that Self is so arcane that some paid tools don’t even check for it. Walkthrough of lab setup, enumeration using free methods & a trial version of this paid tool, abuse, and mitigation.

Welcome to Part XIV 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: Domain dominance in minutes via ACL abuse (i.e. why auditing AD 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

This is another one of those lab projects that was prompted by our adorable little 6 year old Global Admin throwing a crazy idea out there. Mishky brought up a comment that a vendor had made awhile back:

“Specifically, technically speaking, all that one needs to determine is exactly who has Write Property effective permissions to modify the Member attribute on the Domain Admins object, cn=Domain Admins,cn=Users,dc=… in Active Directory.”

You went to state that technically even the following permissions can let you CHANGE the membership of the Domain Admins group >>> GenericAll, GenericWrite, WriteProperty, WriteOwner, WriteDACL and Self

YOU SEE, the ONLY reason these too ALSO allow you to change a group’s membership is exactly BECAUSE they imply Write-Property Member EFFECTIVE PERMISSIONS❗

She thought that since that vendor has a trial version that shows “Who can change the Domain Admins security group’s membership?” we should

  • Give a Domain User WriteOwner, WriteDACL, & Self and see what that tool shows
  • Give a Domain User just Self and check
  • Show free ways to check, both from the attacker and defender’s viewpoint

We went over the Self right in Part XII of our Auditing AD Series here. To quickly recap

  • “Self” is both an ActiveDirectoryRight and an IdentityReference
  • We are focusing on the right here
  • Microsoft calls it something else in the GUI and uses a third term in much of their documentation
  • Although arcane it is something that attackers will gladly use if a misconfiguration gives it to them
  • Hence defenders should be aware of it

Lab Setup

We are going to give Mishka’s Twinsey the Self right to Domain Admins, examine a couple of ways to check for it, and of course show the user taking advantage of it. Mishka called her Twinsey “Yaya” for awhile after she started talking as she couldn’t pronounce the actual name. We are using “Yaya” here since we generally avoid using kid’s real names in these howtos.

Additionally Mishka has three accounts. “Mishka” is her Domain User. “Mishky” is her Domain Admin. She believes in following the best practice of separate privileged user accounts. She also has a Global Admin account in AAD which is not synced with ‘on prem’ AD and is not germane to this howto. Her Domain User account is synced to AAD.

Administrator is of course the builtin SID 500 and ‘Break Glass’ is there for the exact reason it sounds like. These three Domain Admin accounts will be seen again shortly.

We are giving Yaya Self with ObjectType bf9679c0–0de6–11d0-a285–00aa003049e2 :

Import-Module ActiveDirectory
Set-Location AD:

#Give a user Self over a given group
$victim = (Get-ADGroup "Domain Admins" -Properties *).DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity "YaYa").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))
Set-ACL $victim $acl

Verify:

(Get-Acl (Get-ADGroup “Domain Admins”).DistinguishedName).Access | Where-Object {$_.IdentityReference -like “*yaya*”}

What’s this now? The trial version of that vendor’s tool reports that three people can change Domain Admins membership and Yaya is not one of them. It only shows the three Domain Admins we mentioned earlier.

Yet she just added herself. She changed the group’s membership.

We also checked what would show if we gave Yaya WriteOwner, WriteDACL, and Self with bf9679c0–0de6–11d0-a285–00aa003049e2.

Once again, Yaya is not on the list. As we have seen before in numerous howtos such as ‘Do you know who owns your domain?’ and ‘Ownership Matters’, if an attacker has WriteOwner or WriteDACL on a HVT object in AD like Domain Admins then they will take whatever action they want very soon, within seconds if they’re in the CLI.

The attacker’s view

So how would an attacker find this? They could use BloodHound, which even helpfully explains what it means and how to use it.

Here at test.local we are partial to Mishky’s Red Team Tool.

The original PoC codes is below:

#Run/import Get-ADNestedGroups.ps1 first! (Available from: http://blog.tofte-it.dk/powershell-get-all-nested-groups-for-a-user-in-active-directory/)
Import-Module ActiveDirectory
Import-Module .\Get-ADNestedGroups.ps1
Set-Location AD:

$ADRoot = (Get-ADDomain).DistinguishedName
$Accounts = (Get-ADUserNestedGroups (Get-ADUser "$env:username" -Properties *).DistinguishedName).Name
$MyGroups = $Accounts.ForEach{[regex]::Escape($_)} -join '|'
$MyGroups2 = $MyGroups.Replace('\','')
$AlsoCheck = "$env:username|Everyone|Authenticated Users|Domain Users"
$ADCS_Objects = (Get-ADObject -Filter * -SearchBase $ADRoot).DistinguishedName
$DangerousRights = "GenericAll|WriteDACL|WriteOwner|GenericWrite|WriteProperty|Self"
$DangerousGUIDs = "1131f6aa-9c07–11d1-f79f-00c04fc2dcd2|1131f6ad-9c07–11d1-f79f-00c04fc2dcd2|00000000–0000–0000–0000–000000000000|00299570–246d-11d0-a768–00aa006e0529"
$FishyGUIDs = "ab721a56–1e2f-11d0–9819–00aa0040529b|ab721a54–1e2f-11d0–9819–00aa0040529b"

ForEach ($object in $ADCS_Objects)
{
$BadACE = (Get-Acl $object -ErrorAction SilentlyContinue).Access | Where-Object {(($_.IdentityReference -match $MyGroups2) -or ($_.IdentityReference -match $AlsoCheck)) -and (($_.ActiveDirectoryRights -match $DangerousRights) -or ((($_.ActiveDirectoryRights -like "*ExtendedRight*") -and (($_.ObjectType -match $DangerousGUIDs) -or ($_.ObjectType -match $FishyGUIDs))))) -and ($_.AccessControlType -eq "Allow")}
If ($BadACE)
{
Write-Host "Object: $object" -ForegroundColor Red
$BadACE
}
}

This takes about 3 seconds to find the privilege, checks Nested Groups, checks a couple other groups just in case the domain was badly misconfigured, and doesn’t trip Defender or require the AMSI bypass.

The defender’s view

So how would a defender check for this obscure misconfiguration? They could also use BloodHound. They could use BlueHound. Of course we are partial to Mishky’s Blue Team version of Trimarc’s idea to check all groups against a whitelist of those who should have rights to screw with them.

The original PoC code is below:

#Borrowed from Sean Metcalf, works :)
#Basically it scans the ACL of every user account & flags anyone who has DangerousRights and is not a Safe_User
#Most of the variable names are Sean Metcalf's, I just tweaked it to check user accounts instead of AD CS

$ADRoot = (Get-ADRootDSE).rootDomainNamingContext
$DomainSID = (Get-ADDomain).DomainSID.Value
$ADCS_Objects = (Get-ADGroup -Filter * -SearchBase $ADRoot).DistinguishedName
$Safe_Users = "Domain Admins|Enterprise Admins|BUILTIN\\Administrators|NT AUTHORITY\\SYSTEM|$env:userdomain\\CERT Publishers|$env:userdomain\\Administrator|BUILTIN\\Account Operators|$env:userdomain\\<Azure AD Sync account>|$env:userdomain\\<Azure AD Cloud Sync account>|$DomainSID-519|S-1–5–32–548"
$DangerousRights = "GenericAll|WriteDACL|WriteOwner"

ForEach ($object in $ADCS_Objects)
{
$BadACE = (Get-Acl $object).Access | Where-Object {((($_.ActiveDirectoryRights -like "*WriteProperty*") -and (($_.ObjectType -eq "bf9679c0–0de6–11d0-a285–00aa003049e2") -or ($_.ObjectType -eq "bc0ac240-79a9-11d0-9020-00c04fc2d4cf") -or ($_.ObjectType -eq "00000000–0000–0000–0000–000000000000"))) -or ($_.ActiveDirectoryRights -like "*GenericWrite*") -or ($_.ActiveDirectoryRights -like "*GenericAll*") -or ($_.ActiveDirectoryRights -like "*WriteDACL*") -or ($_.ActiveDirectoryRights -like "*WriteOwner*") -or (($_.ActiveDirectoryRights -like "*Self*") -and (($_.ObjectType -eq "bf9679c0–0de6–11d0-a285–00aa003049e2") -or ($_.ObjectType -eq "00000000–0000–0000–0000–000000000000"))) -and ($_.AccessControlType -eq "Allow") -and ($_.IdentityReference -notmatch $Safe_Users))}
If ($BadACE)
{
Write-Host "Object: $object" -ForegroundColor Red
$BadACE
}
}

This flags the privileges we setup in a prior project regarding ScriptPath and Self and of course the Self we just gave out to yaya.

Summary

We talked about getting a more comprehensive picture than just “who has WriteProperty with all 0s?” back in Part IV. This is why. Attackers don’t care about tidy lists. They don’t care if they have to pivot through C to get from A to B. They only care if they can get there. Don’t give them a path.

If a group should not have a privilege then remove the allow statement. If a user should not have a privilege then remove them from the group. Obviously privileges should be given to groups, not users by name. This makes Yaya’s and Test Dummy’s privileges above immediately look suspicious.

The important thing is that you actually check for this stuff and fix what you find.

Stay safe, and remember

PowerShell.exe -EncodedCommand VwByAGkAdABlAC0ASABvAHMAdAAgACcAQwBoAGUAYwBrACAAZgBvAHIAIABEAGEAbgBnAGUAcgBvAHUAcwAgAFIAaQBnAGgAdABzACEAJwAgADsAIABTAHQAYQByAHQALQBTAGwAZQBlAHAAIAAtAFMAZQBjAG8AbgBkAHMAIAAzADAA

(I don’t blame you if you don’t trust us, I wouldn’t trust us either. We showed how to decode the above here.)

References

Self privilege: https://zflemingg1.gitbook.io/undergrad-tutorials/active-directory-acl-abuse/self

Sean Metcalf on DangerousRights: https://adsecurity.org/?p=3658

ADSI on AD GUIDs: http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm

GUIDs matched to name: https://www.powershellgallery.com/packages/DSACL/1.0.0/Content/DSACL.psm1

NT Authority\Self explained: https://ru-facts.com/what-is-nt-authority-self-permission/

--

--

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.