SelfMembership
Summary
FSProtect ACL Alias
SelfMembership
AD Alias
Add/remove self from member
Affected Object Types
Groups
Exploitation Certainty
Certain
AD Attribute
Member
AD Attribute Guid
bf9679c0-0de6-11d0-a285-00aa003049e2
AD Right
Self
Description
The SelfMembership
permission allows a user to add themself as a member of a group in Active Directory, facilitating streamlined group management within the directory hierarchy. This permission operates as a Self
access right on the target's member
attribute.
However, if misconfigured, this permission can introduce a security risk. An attacker can leverage the SelfMembership
permission via the Add-ADGroupMember
command to add themself to a domain group, thereby gaining unauthorized access. Exploiting this vulnerability could allow for privilege escalation and persistent access within the system.
Identification
PowerShell
Active Directory Module
Using the ActiveDirectory PowerShell module, you can enumerate SelfMembership
entries.
1. Find-SelfMembership Function
function Find-SelfMembership {
[CmdletBinding()]
param ([string]$Target,[string]$SearchBase = $null,[string]$OutputPath = "SelfMembershipAcls.csv")
Import-Module ActiveDirectory -ErrorAction Stop
Write-Host "Gathering Active Directory ACLs for explicit Self permissions on the 'member' attribute..."
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow
$ActiveDirectoryRights = [System.DirectoryServices.ActiveDirectoryRights]::Self
$MemberAttributeGuid = "bf9679c0-0de6-11d0-a285-00aa003049e2"
if ($Target) {
Write-Host "Filtering to group '$Target'..."
try {
$objectsToScan = @(
Get-ADGroup -Identity $Target `
-Properties nTSecurityDescriptor `
-ErrorAction Stop
)
}
catch {
Write-Error "Failed to retrieve group '$Target': $($_.Exception.Message)"
return
}
}
else {
$adGroupParams = @{
Filter = "*"
Properties = "nTSecurityDescriptor"
ErrorAction = "Stop"
}
if ($SearchBase) {
$adGroupParams["SearchBase"] = $SearchBase
Write-Host "Searching for all group objects within '$SearchBase'..."
}
else {Write-Host "Searching for all group objects in the domain..." }
try {$objectsToScan = Get-ADGroup @adGroupParams }
catch {
Write-Error "Failed to retrieve Active Directory objects: $($_.Exception.Message)"
return
}
}
if (-not $objectsToScan) {
Write-Output "No group objects found matching the criteria."
return
}
$foundAcls = foreach ($obj in $objectsToScan) {
$dn = $obj.DistinguishedName
try {
$acl = Get-Acl -Path "AD:$dn"
foreach ($ace in $acl.Access) {
if (
$ace.AccessControlType -eq $AccessControlType -and
$ace.ActiveDirectoryRights -band $ActiveDirectoryRights -and
$ace.ObjectType -eq $MemberAttributeGuid -and
-not $ace.IsInherited
) {
[PSCustomObject]@{
Group = $dn
Trustee = $ace.IdentityReference.Value
}
}
}
}
catch {Write-Warning "Could not retrieve ACL for '$dn': $($_.Exception.Message)" }
}
if ($foundAcls) {
$count = $foundAcls.Count
Write-Host "Found $count group object(s) with explicit Self permissions on 'member'."
try {
$foundAcls | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Host "Results exported to '$OutputPath'."
}
catch { Write-Error "Failed to export to CSV '$OutputPath': $($_.Exception.Message)" }
} else { Write-Output "No explicit Self-member ACLs found on any scanned group."}
}
2. Scan all domain groups in the domain
Find-SelfMembership
3. Scan specific group
Find-SelfMembership -Target "Backup Operators"
4. Using SearchBase
to limit the searching scope
Find-SelfMembership -SearchBase "CN=Users,DC=Forestall,DC=Labs"
.NET Directory Services
By leveraging PowerShell’s built-in .NET DirectoryServices namespace, you can enumerate SelfMembership
entries without relying on any external modules or dependencies.
1. Find-SelfMembershipSimple Function
function Find-SelfMembershipSimple {
[CmdletBinding()]
param([string]$Target= $null, [string]$SearchBase= $null, [string]$OutputPath= "SelfMembershipAcls.csv" )
$memberGuid = [guid]"bf9679c0-0de6-11d0-a285-00aa003049e2"
if ($Target) {
Write-Verbose "Binding directly to object: $Target"
try {$entries = @( New-Object System.DirectoryServices.DirectoryEntry("LDAP://$Target") ) }
catch {
Write-Error "Failed to bind to '$Target': $_"
return }
}
else {
Write-Verbose "Binding to RootDSE..."
try {
$root = New-Object System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
$baseDN = $root.Properties["defaultNamingContext"].Value
$ldapPath = if ($SearchBase) { "LDAP://$SearchBase" } else { "LDAP://$baseDN" }
$searchRoot= New-Object System.DirectoryServices.DirectoryEntry($ldapPath)
Write-Verbose "Searching for all group objects under $ldapPath..."
$searcher = [System.DirectoryServices.DirectorySearcher]::new($searchRoot)
$searcher.Filter = "(objectCategory=group)"
$searcher.PageSize = 1000
[void]$searcher.PropertiesToLoad.Add("distinguishedName")
$hits = $searcher.FindAll()
Write-Verbose "Found $($hits.Count) group(s)."
}
catch {
Write-Error "LDAP enumeration failed: $_"
return
}
$entries = foreach ($hit in $hits) {
try { $hit.GetDirectoryEntry() }
catch { Write-Warning "Could not bind entry: $_"; continue }
}
}
$found = foreach ($entry in $entries) {
$dn = $entry.distinguishedName
Write-Verbose "Checking ACLs on: $dn"
try {
$acl = $entry.ObjectSecurity
$aces = $acl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier])
}
catch {
Write-Warning "Could not read ACL for $dn : $_"
continue
}
foreach ($ace in $aces) {
if (
$ace.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and
($ace.ActiveDirectoryRights -band [System.DirectoryServices.ActiveDirectoryRights]::Self) -and
($ace.ObjectType -eq $memberGuid) -and
(-not $ace.IsInherited)
) {
$who = try {
$ace.IdentityReference.Translate([System.Security.Principal.NTAccount]).Value
} catch {
$ace.IdentityReference.Value
}
[PSCustomObject]@{
Group = $dn
Trustee = $who
}
}
}
}
if ($found) {
$found | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Host "Exported $($found.Count) entr$(if($found.Count -eq 1){'y'}else{'ies'}) to $OutputPath"
}
else { Write-Host "No 'member' Self ACLs found."}
}
2. Scan all domain groups in the domain
Find-SelfMembershipSimple
3. Scan a specific group
Find-SelfMembershipSimple -Target "CN=Backup Operators,CN=Builtin,DC=forestall,DC=labs"
4. Using SearchBase
to limit the searching scope
Find-SelfMembershipSimple -SearchBase "CN=Builtin,DC=forestall,DC=labs"
Active Directory Users and Computers
1. Open Active Directory Users and Computers
on your Windows server.
2. Right-click on the group name.
3. Select Properties from the context menu.
4. In the Properties window, navigate to the Security tab.
5. Click on the Advanced button to open the Advanced Security Settings dialog.
6. In the Advanced Security Settings window, locate and select the relevant Access Control Entry (ACE) for the user or group you wish to configure.
7. Click Edit to modify the selected ACE.
8. In the permissions list, locate and check the option Add/remove self from member
Permission.
9. Click OK to save your changes and close the dialogs.

Exploitation
Windows
an attacker can add itself to a group with this cmdlet.
Add-ADGroupMember -Identity "<Vulnerable Group>" -Members "<yourself>"
Example:
Add-ADGroupMember -Identity 'Domain Admins' -Members 'Attacker'

Linux
Add self to group using bloodyAD
bloodyAD --host <dchost> -d <domain> -u <user>> -p '<pass>' add groupMember "<target group>" <user>
Example:
bloodyAD --host FSDC01.forestall.labs -d forestall.labs -u adam -p 'Temp123!' add groupMember "Account Operators" adam

Mitigation
Access Control Entries identified as dangerous should be removed by following the steps below.
1. Open Active Directory Users and Computers
, and activate Advanced Features
option.
2. Double click the affected object and open Security
tab.
3. In this tab, click Advanced
button and open the dangerous Access Control Entry.
4. Remove the rights that are marked as dangerous.
5. Click OK and Apply buttons for saving changes.

Detection
Adding new Access Control Entries on the Active Directory objects changes the ntSecurityDescriptor
attribute of the objects themselves. These changes can be detected with Event IDs 5136 and 4662.. Adding new members to security groups in Active Directory changes the member
attribute of the groups themselves. These changes can be detected with the 4756, 4728, and 4732 Event IDs to identify potentially risky group modifications.
5136
A directory service object was modified.
ntSecurityDescriptor
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5136
4662
An operation was performed on an object.
AccessList, AccessMask
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662
4756
A member was added to a security-enabled universal group
Member, TargetUserName, SubjectUserName, MemberName
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/audit-security-group-management
4728
A member was added to a security-enabled global group
Member, TargetUserName, SubjectUserName, MemberName
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/audit-security-group-management
4732
A member was added to a security-enabled local group
Member, TargetUserName, SubjectUserName, MemberName
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4732
References
Abusing Active Directory ACLs & ACEs (ired.team)Keychron V1 Max
Last updated
Was this helpful?