This blog post is authored by Michael Dubinsky, Principal PM Manager, Microsoft ATA / Azure ATP.
Recently Andy (@_wald0) and Will (@harmj0y), who are amazing contributors to the security community, have published the whitepaper An ACE Up the Sleeve: Designing Active Directory DACL Backdoors.
In this whitepaper they discuss different methods which can be used by attackers to remain persistent and stealthy in the environment to avoid detection.
In general, this is a very important goal for an attacker and is a big part of a successful mission performed either by a nation state or by a hacker group.
Specifically, in the whitepaper Andy and Will mention the option to setup a “Deny” ACE on an object created by the attacker. This will cause the object in question to become invisible (not be returned in LDAP queries performed to the Active Directory), which causes the object to avoid being seen (and monitored) by any service account used by monitoring solutions.
This does sound like an issue, as denying permissions from a Domain Admin principle (or the Everyone principle for that matter) will cause an object to become invisible. A cool idea indeed.
So, this made me think – is there a way we can identify all the objects to which I don’t have permissions?
Sounds like a tough task, however after going through some of the possible resolution APIs together with the ATA security research team, Marina has come across this statement for the LsaLookupSIDs:
Now that we’ve found a method to query a SID and get a result regardless of the ACL we can verify whether the object exists or not.
The next step is to identify whether it’s a permissions issue. In order to validate whether it’s a permissions issue or not, we can compare the results of this API with the LDAP query results.
If only the LsaLookupSIDs returns a result while the LDAP query fails – this means one thing (after cleaning up several bugs related to SidHistory) – we don’t have permissions on the object!
I’ve made a small PowerShell script to demonstrate this capability. The script enumerates all RIDs in a specific domain and compares the LDAP result to the LsaLookupSIDs result to see what I am missing.
The script can be found at https://github.com/michdu/WhatAmIMissing.
This should make discovering ACL hidden objects a little bit easier.