Dangerous Rights Logging Cheatsheet

Rich
7 min readAug 23, 2023

--

TL;DR cheatsheet for setting SACLs, taking the action, how to query the logs to show relevant info, and RE Event IDs.

Welcome to Part IX 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

We went over setting up Windows Event Forwarding and basic tweaking & querying SACLs earlier. This cheatsheet is about

  • Setting the SACL
  • Taking the action
  • Querying the logs
  • Outputting meaningful data

It sounds simple, but due to how Microsoft formats the Message property in a given Event ID this turned into an interesting exercise in data parsing.

We will be dealing with the CEO’s account and the VIPs group throughout this cheatsheet. If one needs to imagine a reason for doing so, then pretend that a business has dictated that certain VIP users & groups require extra auditing.

Set the SACLs

#Audit for Password Reset
$object = (Get-ADUser "CEO").DistinguishedName
$subject = [Security.Principal.NTAccount]"Everyone"
$ObjectType_GUID = [system.guid]"00299570–246d-11d0-a768–00aa006e0529"
$InheritedObjectType_GUID = [system.guid]"00000000–0000–0000–0000–000000000000"
$acl = Get-Acl $object -Audit
$NewRule = New-Object System.DirectoryServices.ActiveDirectoryAuditRule($subject,"WriteOwner","Success",$ObjectType_GUID,"None",$InheritedObjectType_GUID)
$ACL.AddAuditRule($NewRule)
Set-Acl $object $acl

#Confirm
(Get-Acl (Get-ADUser "CEO").DistinguishedName -Audit).Audit
# - - Set auditing rules on a group - -

#Audit for changes to ownership, the DACL, and attributes
$object = (Get-ADGroup "VIPs").DistinguishedName
$subject = [Security.Principal.NTAccount]"Everyone"
$ObjectType_GUID = [system.guid]"00000000–0000–0000–0000–000000000000"
$InheritedObjectType_GUID = [system.guid]"00000000–0000–0000–0000–000000000000"
$acl = Get-Acl $object -Audit
$NewRule = New-Object System.DirectoryServices.ActiveDirectoryAuditRule($subject,"WriteProperty, WriteOwner, WriteDACL","Success",$ObjectType_GUID,"None",$InheritedObjectType_GUID)
$ACL.AddAuditRule($NewRule)
Set-Acl $object $acl

#Confirm
(Get-Acl (Get-ADGroup "VIPs").DistinguishedName -Audit).Audit

Set the DACL

Next we will give a mere Domain User WriteOwner on the VIPs group. This will give us something to abuse as Mishka by seizing ownership, changing the group’s DACL, and adding herself to the group.

(If one wants more details then please see our Set-Acl cheatsheet here.)

Import-Module ActiveDirectory
Set-Location AD:
$root = (Get-ADDomain).DistinguishedName

#Give a user WriteOwner over a given group
$victim = (Get-ADGroup "VIPs").DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity "Mishka").SID
#Allow WriteOwner
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,"WriteOwner","ALLOW",([GUID]("00000000–0000–0000–0000–000000000000")).guid,"None",([GUID]("00000000–0000–0000–0000–000000000000")).guid))
#Apply above ACL rules
Set-ACL $victim $acl

#Confirm
(Get-Acl (Get-ADGroup "VIPs").DistinguishedName).Access | Where-Object {$_.IdentityReference -like "*Mishka*"}

Take the action & seize ownership

Mishka will now

Import-Module ActiveDirectory
Set-Location AD:

#Enumerate
(Get-Acl (Get-ADGroup "VIPs").DistinguishedName).Access | Where-Object {$_.IdentityReference -like "*Mishka*"}

#Take ownership
$target = (Get-ADGroup "VIPs").DistinguishedName
$acl = Get-Acl $target
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser "Mishka").SID
$acl.SetOwner($user)
Set-ACL $target $acl

#Confirm
(Get-Acl (Get-ADGroup "VIPs").DistinguishedName).Owner

Query the logs, show who changed the owner, and to whom

One could simply run the first line alone and pull changes to the VIPs group that happened within the last 30 minutes, or any given timeframe, granted that your logs go that far back.

However one would get some incredibly ugly and barely usable output as a result.

That’s just for the old ACL.

If a user changes an account in most cases there are two Event ID 5136s generated; one marked ‘Value Deleted’ and a second event marked “Value Added”. These two events together show the old and new values.

Hence we can pull both and compare them, then output what changed.

First however we make use of an incredibly useful PowerShell command: ConvertFrom-SddlString

This simple command takes that insanely long, illegible SDDL from the Event ID and outputs something readable.

Further, if we want to see the entire DACL or SACL we can expand the property.

We can then use another incredibly useful command: Compare-Object

On a sidenote, we used the technique from Part IV of Back to the Basics to grab the Properties value number for data points that are in the Message Property of a given Event ID.

Put it all together

$ACL_Events = Get-WinEvent -Path "$env:SystemRoot\System32\Winevt\Logs\ForwardedEvents.evtx" | Where-Object {($_.Id -eq "5136") -and ($_.Message -like "*VIPs*") -and ($_.TimeCreated -ge (Get-Date).AddMinutes(-30))}
$Testing = $ACL_Events | Select-Object -Last 2
$EventII = $Testing[0] #Value Added, aka the new ACL
$EventI = $Testing[1] #Value Deleted, aka the old ACL

If($EventI.Properties[11].Value -eq "nTSecurityDescriptor") #Means the Owner, Group, DACL, SACL, or RawDescriptor changed (we care about the Owner & DACL here)
{
$SDDL_CrapI = $EventI.Properties[13]
$ACLI = ConvertFrom-SddlString -Sddl $SDDL_CrapI.Value -Type ActiveDirectoryRights
$SDDL_CrapII = $EventII.Properties[13]
$ACLII = ConvertFrom-SddlString -Sddl $SDDL_CrapII.Value -Type ActiveDirectoryRights

If(Compare-Object -ReferenceObject $ACLI.Owner -DifferenceObject $ACLII.Owner)
{
$WhatChanged = "Owner"
$OldValue = $ACLI.Owner
$NewValue = $ACLII.Owner
}

If(Compare-Object -ReferenceObject $ACLI.DiscretionaryAcl -DifferenceObject $ACLII.DiscretionaryAcl)
{
$XYZ = Compare-Object -ReferenceObject $ACLI.DiscretionaryAcl -DifferenceObject $ACLII.DiscretionaryAcl
$WhatChanged = "DACL"
$OldValue = $ACLI.DiscretionaryAcl
#If you want to see the entire thing: $ACLChange.OldValue | Format-List
$NewValue = $XYZ
}
} #Close the check on whether the DACL changed

Else
{
$WhatChanged = $EventI.Properties[11].Value
$OldValue = $EventI.Properties[13].Value
$NewValue = $EventII.Properties[13].Value
}
$ACLChange = [PSCustomObject]@{

#Now just tease out the Properties[] value
Target = $EventI.Properties[8].Value
WhatChanged = $WhatChanged
OldValue = $OldValue
NewValue = $NewValue
WhoDunnit = $EventI.Properties[3].Value
DC = $EventI.MachineName
Time = $EventI.TimeCreated
}

Write-Host "An AD object was modified. Details are below."
$ACLChange

Voila, we get nice, legible output showing that Mishka changed the ownership of the VIPs group to herself, what time she did it, and which DC processed the request.

Take the action & change the DACL

#Give a user GenericWrite over a given group
$victim = (Get-ADGroup "VIPs").DistinguishedName
$acl = Get-ACL $victim
$user = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser -Identity "Mishka").SID
#Allow WriteOwner
$acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule $user,"GenericWrite","ALLOW",([GUID]("00000000–0000–0000–0000–000000000000")).guid,"None",([GUID]("00000000–0000–0000–0000–000000000000")).guid))
#Apply above ACL rules
Set-ACL $victim $acl

Query the logs, show who modified the DACL, & what they changed

We run the same query as above. It parses the data depending on whether the owner or the DACL was changed and then outputs accordingly.

We can see that Mishka had WriteOwner before she made the change and afterwards she had GenericWrite, as well as some other rights that fall under it.

Take the action & add yourself to the group

#Mishka adds herself to the VIPs group
Add-ADGroupMember -Identity "VIPs" -Members "Mishka"

Query the logs and show who changed the group membership

Changing a group’s membership creates Event ID 5136, however it was easier to see who had added whom to what group using Event ID 4728.

$GroupChange = Get-WinEvent -Path "$env:SystemRoot\System32\Winevt\Logs\ForwardedEvents.evtx" | Where-Object {($_.Id -eq "4728") -and ($_.Message -like "*VIPs*") -and ($_.TimeCreated -ge (Get-Date).AddMinutes(-30))}

$GroupChanged = [PSCustomObject]@{
#Now just tease out the Properties[] value
Target = (Get-ADGroup -Filter * -Properties * | Where-Object {$_.SID -eq $GroupChange.Properties[4].Value}).DistinguishedName
UserAdded = (Get-ADUser -Filter * -Properties * | Where-Object {$_.SID -eq $GroupChange.Properties[1].Value}).DistinguishedName
WhoDunnit = (Get-ADUser -Filter * -Properties * | Where-Object {$_.SID -eq $GroupChange.Properties[5].Value}).DistinguishedName
DC = $GroupChange.MachineName
Time = $GroupChange.TimeCreated
}

Write-Host "An AD object was modified. Details are below."
$GroupChanged
Some screenshots redacted IOT omit Tiny Human’s real names

Take the action & reset a user’s password

Set-ADAccountPassword -Identity “CEO” -Reset -NewPassword (ConvertTo-SecureString -AsPlainText “Summer2023!!” -Force)

Query the logs & show who reset the password

We are looking for Event ID 4724.

$pwdReset = Get-WinEvent -Path "$env:SystemRoot\System32\Winevt\Logs\ForwardedEvents.evtx" | Where-Object {($_.Id -eq "4724") -and ($_.Message -like "*CEO*") -and ($_.TimeCreated -ge (Get-Date).AddMinutes(-30))}
$Target = (Get-ADUser -Filter * | Where-Object {$_.SID -eq $pwdReset.Properties[2].Value}).DistinguishedName
$Subject = (Get-ADUser -Filter * | Where-Object {$_.SID -eq $pwdReset.Properties[3].Value}).DistinguishedName

$Reset = [PSCustomObject]@{
#Now just tease out the Properties[] value
Target = $Target
WhoDunnit = $Subject
DC = $pwdReset.MachineName
Time = $pwdReset.TimeCreated
}

Write-Host "An AD password was reset. Details are below."
$Reset

Summary

This is a cheatsheet regarding setting SACLs and querying the collected logs. It is not a defense strategy by itself.

Detection is a distant second to prevention. Audit who holds ‘Dangerous Rights’ and clean up any Misconfiguration Debt before an attacker can take actions like those listed above.

Additionally, there are nice, easy to use paid tools out there from companies like NetWrix that will alert you if someone makes changes to AD that they shouldn’t be doing.

We are just big fans of trying stuff out in the lab for free and learning along the way.

References

Event ID 5143: https://www.socinvestigation.com/threat-hunting-using-windows-event-id-5143/

PSCustomObject: https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.3

ConvertFrom-SddlString: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-sddlstring?view=powershell-7.3

Find the difference: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/compare-object?view=powershell-7.3

Eventopedia, only mildly useful: http://eventopedia.cloudapp.net/default.aspx?LogType=Windows+Event+Log&LogName=InTrust+for+AD&Source=ITAD+Directory+Changes&EventID=44&action=go

NetWrix AD Change Reporter: https://www.netwrix.com/active_directory_auditing.html

Auditing in AD IOT catch unapproved changes: https://techcommunity.microsoft.com/t5/core-infrastructure-and-security/who-moved-the-ad-cheese/ba-p/255596

--

--

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.