TL;DR ChatGPT can give you a starting point, but don’t trust it to get everything right. Walkthrough of ChatGPT’s answer and what it missed.
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: 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
Here at test.local we have nothing against AI and have found ChatGPT helpful at times. However in our humble opinion one should not always trust it to get more complex queries correct. We asked it some of the questions posed by a certain vendor in the AD auditing space, namely
- Who can execute DCSync?
- Who can modify the Domain Admins group membership?
At first it provided a partially incorrect answer to ‘who can DCSync’, stating that it had to do with who could modify the DC’s OU. This isn’t wrong per se, after all an attacker who can create a GPO and link it to the DC’s OU is likely minutes away from being able to DCSync. However it is also incomplete. Anyone who has the right privileges in AD can DCSync immediately, as we have seen earlier here.
Lately ChatGPT has been getting those privileges right, but provides only a partially correct way to query for who has them.
Now it gets interesting
In answer to ‘who can change the Domain Admin’s membership’ ChatGPT provided us an odd command to use ‘Get-ADPermission’.
#ChatGPT's code, doesn't work at all:
$DomainAdminsGroup = Get-ADGroupMember -Identity "Domain Admins"
$Permissions = Get-ADPermission -Identity $DomainAdminsGroup.DistinguishedName
$ChangeMembersRights = $Permissions | Where-Object { $_.ExtendedRights -like "*Change Group Membership*" }
$ChangeMembersRights | Select-Object -ExpandProperty User
Nifty command, why didn’t we use it earlier instead of Get-Acl?
Exchange
The answer, which ChatGPT didn’t mention, is that Get-ADPermission is one of many commands that requires both an Exchange server and rights in Exchange to use.
This is test.local, and we don’t much care for theory, so we jumped on Microsoft’s Evaluation Center and grabbed a copy of the ISO. We spun up a member server in ESXi to host it, got all the requirements installed, and got Exchange up and running.
We had been meaning to stand up Exchange eventually so we would be ready to work on Exchange hybrid, so this was a good reason to do so.
Using the Exchange Management Shell
CW6 Google and Microsoft Learn let us know that the Exchange Management Shell
Can be used in PowerShell either locally or remotely 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 we connected our adorable little Global Admin said “bro, instead of ChatGPT’s convoluted query just”:
Get-ADPermission (Get-ADGroup "Domain Admins").DistinguishedName | Where-Object { $_.ExtendedRights -like "*Change Group Membership*" } | Format-List
But of course this didn’t return anything.
What ChatGPT missed
I don’t blame ChatGPT for this. I have seen vendors get this wrong.
In short:
- There are other rights that include this (GenericAll, GenericWrite, WriteProperty with all 0s, etc)
- There are rather obscure rights (Self with all 0s or a specific GUID)
- There are rights that give someone the ability to give themselves the right (WriteOwner, WriteDACL, etc)
One of the first things we asked ChatGPT when it first hit the news was “Who can modify the Domain Admins membership?” and got back a query for WriteProperty with ObjectType bf9679c0–0de6–11d0-a285–00aa003049e2.
Anyone who ever even glanced at the advanced security tab in ADUC knows that’s wildly incomplete. If they’ve queried ACLs in PowerShell they definitely know that.
The reason that ChatGPT’s query didn’t return anything is that by default no one has specifically that and only that privilege in the AdminSDHolder.
A better query is:
(Get-Acl (Get-ADGroup "Domain Admins").DistinguishedName).Access | Where {((($_.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"))} | Select-Object IdentityReference, ActiveDirectoryRights, ObjectType
Or just use Mishky’s Blue Team auditor to check for any non-whitelisted entities who hold ‘Dangerous Rights’.
We went over this in Part IV and Annex D, so I won’t beat a dead horse here, at least not too much.
Sidenote; Get-Acl vs Get-ADPermission
As we saw above one has to connect to the Exchange Management Shell first, but as long as that was done then Get-Acl and Get-ADPermission use very similar syntax. This example shows the ACE in giving the Organization Management group GenericAll on Domain Admins.
(Get-Acl (Get-ADGroup "Domain Admins").DistinguishedName).Access | Where-Object {($_.IdentityReference -like "*Organization Management*") -and ($_.ActiveDirectoryRights -like "*GenericAll*")}
Get-ADPermission (Get-ADGroup "Domain Admins").DistinguishedName | Where-Object {($_.User -like "*Organization Management*") -and ($_.AccessRights -like "*GenericAll*")} | Format-List
The big differences:
- Get-ADPermission uses different terms in the ACE
- Get-ADPermission resolves GUIDs
We made a quick & dirty cheatsheet for Get-ADPermission here. As long as you have Exchange it does have easy to read output.
Random Exchange notes
Add-ADPermission is an old command, but Microsoft tends to keep legacy stuff around, so it still works if one has Exchange and really wants to use it. While the intention was probably for delegating Send As or Receive As rights on a user account, it can work for other rights as well.
Add-ADPermission -Identity "Test Dummy" -User "Mishka" -AccessRights ExtendedRight -ExtendedRights "Send As"
I will definitely give ChatGPT credit here. If you have Exchange setup and have rights to use its Management Shell then the syntax for Add-ADPermission is much simpler and more straightforward than Set-Acl’s.
We can create Test Dummy’s email account via:
Enable-Mailbox -Identity "Test.Dummy"
Summary
I’ll stress again, we have nothing against AI. Our adorable little Global Admin loves “talking to” ChatGPT.
I just wouldn’t recommend trusting its answers to more complex questions without double checking as well.
In this case it did provide us a good learning experience and a reason to finally get around to setting up Exchange.
References
ChatGPT accuracy over time: https://www.republicworld.com/business-news/international-business/chatgpt-loses-charm-among-heavy-users-study-reveals-drop-in-capability-over-time-articleshow.html
Deploying Exchange: https://learn.microsoft.com/en-us/exchange/plan-and-deploy/deploy-new-installations/install-mailbox-role?view=exchserver-2019
Get-ADPermission: https://learn.microsoft.com/en-us/powershell/module/exchange/get-adpermission?view=exchange-ps
Check & update .NET: https://www.thecodeasylum.com/use-powershell-to-check-net-version-and-update-as-needed/
Azure Arc info: https://learn.microsoft.com/en-us/windows-server/administration/overview
.NET 4.8 installer: https://support.microsoft.com/en-us/topic/microsoft-net-framework-4-8-offline-installer-for-windows-9d23f658-3b97-68ab-d013-aa3c3e7495e0
Exchange Management Shell: https://learn.microsoft.com/en-us/powershell/exchange/exchange-management-shell?view=exchange-ps
Connect to Exchange from PowerShell: https://learn.microsoft.com/en-us/powershell/exchange/connect-to-exchange-servers-using-remote-powershell?view=exchange-ps
Add-ADPermission: https://learn.microsoft.com/en-us/powershell/module/exchange/add-adpermission?view=exchange-ps
Get-ADPermission: https://learn.microsoft.com/en-us/powershell/module/exchange/get-adpermission?view=exchange-ps
Exchange, next steps: https://learn.microsoft.com/en-us/exchange/plan-and-deploy/post-installation-tasks/post-installation-tasks?view=exchserver-2019
Enable-Mailbox: https://learn.microsoft.com/en-us/powershell/module/exchange/enable-mailbox?view=exchange-ps
Changes made to AdminSDHolder by Exchange: https://learn.microsoft.com/en-us/answers/questions/907503/genericall-acl-on-domain-admins-group
ObjectType 018849b0-a981–11d2-a9ff-00c04f8eedd8: https://www.powershellgallery.com/packages/SDDLParser/0.5.0/Content/SDDLParserADObjects.ps1