Fix source_kind contamination of AD nodes via two-step upload (#25)#26
Merged
Merged
Conversation
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.
Linked Issue
Closes #25
Root Cause
The collector built a single graph with
NewOpenGraph(KindKeyCredentialBase)and added every edge to it, including theHasKeyCredentialedges whose start endpoint is an existing AD principal (objectSid) not emitted by this collector. Since #15 the export emitsmetadata.source_kind. Per the BloodHound OpenGraph contract, a payload that setsmetadata.source_kindand references existing AD/AZ nodes stamps that source kind onto the referenced nodes; deleting the source kind then deletes them. Mixing the collector's own nodes with cross-collector edges in one source-kind payload therefore put legitimate AD User/Computer nodes at risk of deletion.Fix Description
Adopt the documented two-step upload.
ParseResultsnow takes a second graph,ogCrossCollector, created with an empty source kind. The collector's own nodes andHasKeyMaterialedges stay in the source-kind graph (og); the cross-collectorHasKeyCredentialedges go intoogCrossCollector.mainwrites two files: the main<output>.json(withmetadata.source_kind) and<output>_cross_collector.json(no metadata, because an empty source kind suppresses the metadata block). Export was factored into awriteGraphhelper and the cross filename intocrossCollectorOutputFile. The README documents the two files and the required upload order.How Verified
"metadata": {"source_kind": "KeyCredentialBase"}; the cross-collector graph (NewOpenGraph(""),ExportJSON(true)) contains nometadata/source_kindblock. Confirmed againstgopengraph/OpenGraph.go:577where the metadata block is gated ong.sourceKind != "".TestCrossCollectorOutputFilecovers the filename derivation;go test ./...passes.go build ./...,go vet ./..., andgofmt -l(no output) pass.Test Coverage
Added:
main_test.go/TestCrossCollectorOutputFilecovers the_cross_collectorfilename derivation across extension, no-extension, nested-path, and non-.jsoncases. The graph-routing change itself has no fixture harness (requires live LDAP) and was verified at runtime as described above.Scope of Change
parse.go,main.go,README.md,main_test.goRisk and Rollout
Local to the collector. Operators must now upload two files (main first, then cross-collector). Existing single-file workflows must add the second upload to keep the
HasKeyCredentialedges. Safe to merge.