Skip to content

Feature: Add collection of Active Directory Sites ACLs and data#186

Open
q-roland wants to merge 6 commits into
SpecterOps:2.Xfrom
q-roland:AD_sites
Open

Feature: Add collection of Active Directory Sites ACLs and data#186
q-roland wants to merge 6 commits into
SpecterOps:2.Xfrom
q-roland:AD_sites

Conversation

@q-roland

@q-roland q-roland commented Nov 6, 2025

Copy link
Copy Markdown

Description

This pull requests aims to integrate Active Directory Sites into the data collected from the configuration partition.
This pull request goes with the following Bloodhound PR: SpecterOps/BloodHound#2031
It is also accompanied by the following SharpHoundCommon PR: SpecterOps/SharpHoundCommon#257
A more complete description on why we thought this could be a good idea is described in details in the BloodHound PR, as well as the following article that we just released: https://www.synacktiv.com/en/publications/site-unseen-enumerating-and-attacking-active-directory-sites

Motivation and Context

Motivation and context are explained in the linked article.

How Has This Been Tested?

This has for the moment been tested in local lab instances. The lab instance was composed of various Active Directory site configurations:

  • Single site
  • 2 sites with associated subnets and 1 server by site
  • 3 sites with several servers by site.

Screenshots (if appropriate):

See the BloodHound PR and linked article for screenshots.

Types of changes

  • Chore (a change that does not modify the application functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • Documentation updates are needed, and have been made accordingly.
  • I have added and/or updated tests to cover my changes.
  • All new and existing tests passed.
  • My changes include a database migration.

As was mentioned in the BloodHound pull request, this is of course only an implementation suggestion, and I remain open to discussion about the choices that were made, requests for implementation changes and so on!

Cheers,

Summary by CodeRabbit

Summary

  • New Features

    • Added Site as a supported --collectionmethods option.
    • Enabled site-level collection and export for Site, SiteServer, and SiteSubnet, including additional relationship and ACL-related details where applicable.
    • Extended export outputs to include the new site data types in generated archives.
  • Documentation

    • Updated CLI help for --collectionmethods to list Site.
    • Refreshed PowerShell Invoke-BloodHound help for collection-method presets, including the Site entry.

* Process data associated with sites, sites servers, sites subnets
* Add collection method "site", included in default collection methods
@coderabbitai

coderabbitai Bot commented Nov 6, 2025

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b620871d-9e83-4429-b190-0f1490ea7df3

📥 Commits

Reviewing files that changed from the base of the PR and between 96afd60 and d3e34da.

📒 Files selected for processing (1)
  • src/Runtime/OutputWriter.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Runtime/OutputWriter.cs

Walkthrough

Active Directory Site objects (Sites, SiteServers, SiteSubnets) are added as a collection method through command-line option parsing, runtime object processing with ACL handling and containment deduction, output serialization, and documentation updates.

Changes

Site Collection Method Integration

Layer / File(s) Summary
Options and Enum Registration
src/Options.cs
Site collection method is registered in command-line help text and mapped to its internal enum value via ResolveCollectionMethods switch logic.
Object Processing Setup
src/Runtime/ObjectProcessors.cs
ObjectProcessors gains a SiteProcessor field, instantiates it in the constructor, and extends ProcessObject to route Label.Site, Label.SiteServer, and Label.SiteSubnet objects to new handlers.
Site/SiteServer/SiteSubnet Handlers
src/Runtime/ObjectProcessors.cs
Three new private methods (ProcessSiteObject, ProcessSiteServerObject, ProcessSiteSubnetObject) process respective object types by populating common properties, optionally handling ACLs and inheritance flags, merging LDAP properties when ObjectProps is enabled, deducing containment relationships via SiteProcessor, and reading GP links (Site only).
Output Pipeline Integration
src/Runtime/OutputWriter.cs
OutputWriter adds JsonDataWriter fields for Site, SiteServer, and SiteSubnet objects, initializes them in the constructor, extends StartWriter to dispatch these types, flushes them during FlushWriters, and includes their output filenames in ZipFiles.
Documentation Updates
README.md, src/PowerShell/Template.ps1
README and PowerShell help text are reformatted and extended to include Site as a supported collection method option with preset descriptions.

Sequence Diagram

sequenceDiagram
    participant Parser as Options Parser
    participant ObjProc as ObjectProcessors
    participant SiteProc as SiteProcessor
    participant Handler as Site Handlers
    participant Writer as OutputWriter
    
    Parser->>ObjProc: Route Site/SiteServer/SiteSubnet objects
    
    rect rgba(100, 150, 200, 0.5)
    Note over ObjProc,Handler: Object Processing Phase
    ObjProc->>Handler: Dispatch to handler (Site/SiteServer/SiteSubnet)
    Handler->>Handler: Populate common properties
    Handler->>Handler: Process ACLs if enabled
    Handler->>Handler: Merge LDAP properties if enabled
    end
    
    rect rgba(150, 100, 200, 0.5)
    Note over Handler,SiteProc: Relationship Resolution
    Handler->>SiteProc: Get containing site/referenced computer/subnet containment
    SiteProc-->>Handler: Return relationship data
    Handler->>Handler: Set ContainedBy and relationship fields
    end
    
    Handler->>Handler: Read GP links if Site + collection enabled
    Handler->>Writer: Accept processed object
    
    rect rgba(200, 150, 100, 0.5)
    Note over Writer: Serialization Phase
    Writer->>Writer: Write to JsonDataWriter
    Writer->>Writer: Flush writers on completion
    Writer->>Writer: Archive output files
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Poem

🐰 A warren of Sites now takes form,
With Servers and Subnets in swarm,
ACLs unwind through each new bind,
Containment traced, relationships signed!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature being added: collection of Active Directory Sites ACLs and data, which aligns with the primary purpose shown in the changeset across multiple files.
Description check ✅ Passed The description includes most key sections (Description, Motivation and Context, How Has This Been Tested, Types of changes) and provides linked references for additional context; however, the Documentation and Testing checklist items are explicitly unchecked.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Runtime/OutputWriter.cs (1)

219-220: Minor formatting: missing space after comma.

Line 219 is missing a space between _certTemplateOutput.GetFilename(), and _issuancePolicyOutput.GetFilename().

Apply this diff:

-                _certTemplateOutput.GetFilename(),_issuancePolicyOutput.GetFilename(),
+                _certTemplateOutput.GetFilename(), _issuancePolicyOutput.GetFilename(),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc420a6 and ebc3743.

📒 Files selected for processing (4)
  • src/Client/Enums.cs (1 hunks)
  • src/Options.cs (2 hunks)
  • src/Runtime/ObjectProcessors.cs (4 hunks)
  • src/Runtime/OutputWriter.cs (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/Runtime/ObjectProcessors.cs (2)
src/Runtime/OutputWriter.cs (2)
  • Task (108-170)
  • Task (172-193)
src/Client/Context.cs (2)
  • Task (72-72)
  • Dictionary (23-27)
src/Runtime/OutputWriter.cs (1)
src/Writers/JsonDataWriter.cs (3)
  • JsonDataWriter (19-119)
  • JsonDataWriter (33-47)
  • GetFilename (115-118)
🔇 Additional comments (7)
src/Options.cs (1)

17-17: LGTM! Site collection method properly integrated.

The Site option is correctly added to the help text and mapped in the switch statement, consistent with existing collection methods.

Also applies to: 211-211

src/Client/Enums.cs (1)

34-34: LGTM! Enum member correctly positioned.

The Site enum member is properly placed and aligns with the mapping in Options.cs.

src/Runtime/OutputWriter.cs (1)

38-40: LGTM! Site-related output writers properly integrated.

The three new writers (Site, SiteServer, SiteSubnet) follow the established pattern consistently across field declarations, constructor initialization, routing in StartWriter, and flushing.

Also applies to: 64-66, 155-163, 187-189

src/Runtime/ObjectProcessors.cs (4)

42-42: LGTM! SiteProcessor properly initialized.

The SiteProcessor field and constructor initialization follow the established pattern used by other processors.

Also applies to: 64-64


100-105: LGTM! Switch cases properly route Site-related labels.

The three new case statements correctly dispatch Site, SiteServer, and SiteSubnet objects to their respective processing methods.


1049-1052: Verify: ContainedBy logic nested under ObjectProps rather than Container flag.

The containing site for subnets is determined inside the ObjectProps conditional block (lines 1037-1053) rather than a Container check. While the comment on lines 1047-1048 explains this requires reading the siteObject property, this creates an inconsistency: the ContainedBy field won't be populated if ObjectProps isn't enabled, even when Container collection is active.

Consider whether the site lookup could be moved under a Container flag check, or if ObjectProps should implicitly enable the required property reads for containment.


970-970: Verify: GP link reading inconsistency in ProcessSiteObject requires developer confirmation

The inconsistency identified in the review is confirmed. ProcessDomainObject (line 530) and ProcessOUObject (line 603) both guard GP link reading with if (_methods.HasFlag(CollectionMethod.Container)), but ProcessSiteObject (line 970) reads GP links unconditionally without checking the Container flag.

Other conditional properties in ProcessSiteObject (ACL, ObjectProps) follow the flag-based pattern, making this inconsistency stand out. No comments explain why Site differs.

This requires developer verification: is the unconditional GP link reading for Site intentional (perhaps Site objects always require links regardless of collection settings), or is it a bug that should follow the Domain/OU pattern?

Comment thread src/Runtime/ObjectProcessors.cs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants