SharpHound3 icon indicating copy to clipboard operation
SharpHound3 copied to clipboard

GPOLocalGroup not returning data without including All

Open dievus opened this issue 3 years ago • 10 comments

Good morning,

While working through Rastamouse's CRTO course, it was identified that running GPOLocalGroup alone as a Sharphound query was not returning full GPOLocalGroup data. Him and I worked through the issue for some time before realizing that GPOLocalGroup wasn't querying the appropriate data from the execution.

The following was ran in domain user context - sharphound.exe -c gpolocalgroup image

And the contents of the json file below -

{"groups":[{"Properties":{"name":"ENTERPRISE DOMAIN [email protected]","domain":"CYBERBOTIC.IO"},"Members":[{"MemberId":"S-1-5-21-3865823697-1816233505-1834004910-1000","MemberType":"Computer"}],"ObjectIdentifier":"CYBERBOTIC.IO-S-1-5-9","Aces":[]},{"Properties":{"name":"[email protected]","domain":"CYBERBOTIC.IO"},"Members":[{"MemberId":"S-1-5-21-3865823697-1816233505-1834004910-515","MemberType":"Group"},{"MemberId":"S-1-5-21-3865823697-1816233505-1834004910-513","MemberType":"Group"}],"ObjectIdentifier":"CYBERBOTIC.IO-S-1-1-0","Aces":[]},{"Properties":{"name":"AUTHENTICATED [email protected]","domain":"CYBERBOTIC.IO"},"Members":[{"MemberId":"S-1-5-21-3865823697-1816233505-1834004910-515","MemberType":"Group"},{"MemberId":"S-1-5-21-3865823697-1816233505-1834004910-513","MemberType":"Group"}],"ObjectIdentifier":"CYBERBOTIC.IO-S-1-5-11","Aces":[]}],"meta":{"count":3,"type":"groups","version":3}}

Running with the all flag appended ran from a domain context, the results were appropriate and as follows -

sharphound.exe -c all gpolocalgroup

Resolved Collection Methods: Group, Sessions, LoggedOn, Trusts, ACL, ObjectProps, LocalGroups, SPNTargets, Container, GPOLocalGroup [+] Creating Schema map for domain CYBERBOTIC.IO using path CN=Schema,CN=Configuration,DC=cyberbotic,DC=io [+] Cache File not Found: 0 Objects in cache [+] Pre-populating Domain Controller SIDS Status: 0 objects finished (+0) -- Using 34 MB RAM Status: 197 objects finished (+197 6.793103)/s -- Using 46 MB RAM Status: 198 objects finished (+1 6)/s -- Using 50 MB RAM Enumeration finished in 00:00:33.3755922 Compressing data to .\20210331180317_BloodHound.zip You can upload this file directly to the UI SharpHound Enumeration Completed at 18:04 on 31/03/2021! Happy Graphing!

This execution included the appropriate GPOLocalGroup data as expected, but required the All flag to do so.

In the end, I'm not sure if it's intended that the GPOLocalGroup flag require the All flag as well. I appreciate you looking in to this.

Thank you!

dievus avatar Apr 01 '21 12:04 dievus

I also came across this issue during the OSEP course!

0xbad53c avatar May 18 '21 19:05 0xbad53c

I had a similar need (to only inspect GPO data). I saw the same problem as described above and work around like this: sharphound.exe -c GPOLocalGroup,Container

Maybe this will help if users don't want to use the "All" option.

mark-lowe avatar Sep 09 '21 21:09 mark-lowe

The issue seems to be the flags=* filter on some queries.

In LdapBuilder file, there are all the LDAP queries to filter results. The Container query is here: https://github.com/BloodHoundAD/SharpHound3/blob/master/SharpHound3/LdapBuilder.cs#L81

ldapFilterParts.Add("(|
	(&(&(objectcategory=groupPolicyContainer)(flags=*))(name=*)(gpcfilesyspath=*)) // Either this
	(objectcategory=organizationalUnit)(objectClass=domain) // Or this
)");

The second filter is way more permissive, and doesn't contain the flag=* restriction.

The GPOLocalGroup LDAP query is the following https://github.com/BloodHoundAD/SharpHound3/blob/master/SharpHound3/LdapBuilder.cs#L90

ldapFilterParts.Add("(&(|(objectcategory=organizationalUnit)(objectclass=domain))(gplink=*)(flags=*))");

The queries filters out all objects with LDAP attribute flags unset.

In my AD, all my OU and Domain objects have this attribute unset.

I'm not sure what is this attribute used for, and if it's really necessary, but in my experience, it's not used.

I wrote a PR for this: https://github.com/BloodHoundAD/SharpHound3/pull/45

Hackndo avatar Nov 22 '21 13:11 Hackndo

So this change was actually made because of this: https://github.com/BloodHoundAD/SharpHound2/pull/65

I'm going to have to figure out how to reconcile this, maybe make it a flag

rvazarkar avatar Nov 22 '21 14:11 rvazarkar

That's interesting, I was wondering why this flag was checked. In my environment (default AD install), this attribute exists, but is always unset.

In the request you linked, @Crypt0-M3lon says:

The patch just add a check for the flags attribute existence

I'm not sure if attribute existence means that the versioned GPO doesn't have this attribute at all, or if it's unset.

I suspect the attribute always exists, and is always unset, except when using Group Policy Admin. What I read is that this flag is never used by MS, only by third party whenever they need to store some flags somewhere. So my guess is that "Group Policy Admin" uses this attribute to allow multiple versioned GPOs. (https://social.technet.microsoft.com/Forums/ie/en-US/82ee9319-3ced-4be8-8110-d708a0f019ca/active-directory-attribute-can-we-use-the-flags-attribute?forum=winserverDS It is for admins to use as desired)

In the meantime, I'd say that the code shouldn't break for default install (meaning this flag shouldn't be checked), and we should think of a solution to have valid result for third party software like "Group Policy Admin".

edit: maybe make it a flag, yes that could be a solution. By default, there's no filter, but by specifying something on the CLI, it would add the filter.

Hackndo avatar Nov 22 '21 14:11 Hackndo

Oh sorry to hear you had issues with my old fix :( Unfortunately I have no more access to the domain with GPA to try to find a decent solution.

Crypt0-M3lon avatar Nov 22 '21 14:11 Crypt0-M3lon

Oh I realized that the line was not changed in my commit but in this one: https://github.com/BloodHoundAD/SharpHound3/commit/15733d74a28233e4736fcea3b19b3a4ad68e6ce2#diff-795fcb0de4314b310b193b37cf9de3ac816711cdf1153a0feb66ec7fe68aacafR90 and I'm pretty sure that there were no regression with my fix back in time. GPO MUST have a flags (https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gpod/d360d288-d7d5-49a9-83be-603805da1379), a grouppolicycontainer without a flag is not a valid, probably from a versioning tools. But you are looking for the flag attribute on a organizationalUnit which is not attended, should not the fix be to remove the extra flags checks from ldapFilterParts.Add("(&(|(objectcategory=organizationalUnit)(objectclass=domain))(gplink=*)(flags=*))"); ?

Crypt0-M3lon avatar Nov 22 '21 15:11 Crypt0-M3lon

Yes, it should. Now I understand: this flags attribute must be set on GPC, but not on OU. The filter was added on OU and Domain objects, which is not correct. My PR related to this issue removes this flag from all queries when used alongside OU & Domain, so I guess it's a valid fix.

Thank you @Crypt0-M3lon for details! :)

Hackndo avatar Nov 22 '21 15:11 Hackndo

FWIW, this isn't an issue in the new common library

https://github.com/BloodHoundAD/SharpHoundCommon/blob/master/src/CommonLib/LDAPQueries/LDAPFilter.cs

Looks like I got the filters right there.

I'm currently working on a new SH version using this with release date TBA

rvazarkar avatar Nov 22 '21 17:11 rvazarkar

Ok, seems good indeed. Thank you @rvazarkar If you need beta-testing, I'm available ;)

Hackndo avatar Nov 23 '21 09:11 Hackndo