Repository navigation
fix: only count ACEs that actually grant Full Control on System Manag… - #14
Merged
Merged
Conversation
…ement
_parse_sd_generic_all read the access mask and nothing else. It decoded the
object-ACE flags purely to work out where the SID started, then threw the
meaning away, and it never looked at AceFlags at all.
Exchange's setup /PrepareAD writes ACEs at the domain root for Exchange
Trusted Subsystem and Organization Management with a 0x000F01FF mask, and
they inherit down onto CN=System Management. None of them grant anything on
the container:
- some are INHERIT_ONLY, present only so AD can copy them to child objects
- the rest carry an ObjectType GUID, which scopes the mask to a single
Exchange property set, or an InheritedObjectType GUID, which scopes it
to one child object class
Both got reported as GenericAll. _expand_group_targets then walked Exchange
Trusted Subsystem and registered every Exchange server as a scan target.
Checked against a real domain DACL: 10 principals reported, of which only
the site server and the SCCM group were real.
Now skip INHERIT_ONLY ACEs, skip object ACEs carrying either GUID, and skip
LOCAL SYSTEM / BUILTIN\Administrators / CREATOR OWNER. Plain and
container-inherit ACEs are unaffected.
tests/ldap_smc_dacl_scope_test.py covers both directions with synthetic
descriptors: five of the eight cases fail without this change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Same problem in garrettfoster13/sccmhunter#139 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's wrong
In a domain running Exchange, the LDAP collector reports Exchange Trusted Subsystem and Organization Management as holding GenericAll on
CN=System Management. Neither does._expand_group_targetsthen walks Exchange Trusted Subsystem and registers every Exchange server as a scan target, so the whole per-host pipeline runs against them._parse_sd_generic_all(src/openhound_sccm/collectors/ldap.py:786) reads the access mask and nothing else. It never touchesAceFlags, and it decodes the object-ACE flags only to work out where the SID starts before throwing the meaning away.An access mask of
0x000F01FFon its own doesn't mean Full Control:INHERIT_ONLY(0x08) grants nothing on this container. It's there so AD can copy it to child objects.ObjectTypeGUID grants its mask over one property set or extended right, not over the object. One with anInheritedObjectTypeGUID only applies to child objects of that class.Exchange's
setup /PrepareADwrites both kinds at the domain root with that exact mask, and they inherit down onto System Management.What it looks like
A System Management descriptor from an Exchange domain, fed to
_parse_sd_generic_all:Exchange Trusted Subsystem had three ACEs there. One scoped by
ObjectType, twoINHERIT_ONLYand scoped byInheritedObjectType. Its members are the Exchange servers that were being collected.The fix
AceFlagsand skipINHERIT_ONLYACEsACE_OBJECT_TYPE_PRESENTorACE_INHERITED_OBJECT_TYPE_PRESENTBUILTIN\Administrators, CREATOR OWNERPlain and container-inherit ACEs are unaffected, so real site servers and the group holding Full Control still come through. Each skip writes a debug line.
Tests
tests/ldap_smc_dacl_scope_test.py, 8 cases on synthetic descriptors. Plain ACE kept, container-inherit ACE kept, unscoped object ACE kept,INHERIT_ONLYdropped, both scoped object ACE shapes dropped, built-in principal dropped, plus one case shaped like a real Exchange-domain DACL.I checked they catch the bug rather than just passing: reverted the parser to
HEADand 5 of the 8 failed, restored it and all 8 passed. Full suite is 1048 passed, 5 skipped.Same bug in the deprecated PowerShell
powershell_deprecated/ConfigManBearPig.ps1:3458has this problem plus a worse one:Missing
-andon the second line. Only the last statement is the filter output, so every ACE that isn't NT AUTHORITY passes, Allow or Deny, GenericAll or not. Not touched here since it's deprecated, but worth knowing if anyone reads it.🤖 Generated with Claude Code