Skip to content

Commit

Permalink
ESC6B: Post processing (#370)
Browse files Browse the repository at this point in the history
* add 6b to ad.cue

* working on logic for 6b

* add esc 6b harness template 1.json

* add test and static assets for esc6b template 1

* test based on eca harness

* test based on principal edges harness

* test based on template 2

* add static assets for all test cases

* copyright was erroneously removed
  • Loading branch information
brandonshearin authored Jan 31, 2024
1 parent d52d17b commit fee4256
Show file tree
Hide file tree
Showing 15 changed files with 4,164 additions and 35 deletions.
250 changes: 250 additions & 0 deletions cmd/api/src/analysis/ad/adcs_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package ad_test

import (
"context"

"github.com/specterops/bloodhound/analysis"
"github.com/specterops/bloodhound/analysis/impact"
"github.com/specterops/bloodhound/graphschema"
Expand Down Expand Up @@ -957,6 +958,255 @@ func TestADCSESC6a(t *testing.T) {
})
}

func TestADCSESC6b(t *testing.T) {
testContext := integration.NewGraphTestContext(t, graphschema.DefaultGraphSchema())

testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
harness.ESC6bTemplate1Harness.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC6b template 1")

groupExpansions, err := ad2.ExpandAllRDPLocalGroups(context.Background(), db)
require.Nil(t, err)
enterpriseCertAuthorities, err := ad2.FetchNodesByKind(context.Background(), db, ad.EnterpriseCA)
require.Nil(t, err)
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
require.Nil(t, err)
domains, err := ad2.FetchNodesByKind(context.Background(), db, ad.Domain)
require.Nil(t, err)

cache := ad2.NewADCSCache()
cache.BuildCache(context.Background(), db, enterpriseCertAuthorities, certTemplates)

for _, domain := range domains {
innerDomain := domain

for _, enterpriseCA := range enterpriseCertAuthorities {
if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
innerEnterpriseCA := enterpriseCA

operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
if err := ad2.PostADCSESC6b(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
t.Logf("failed post processing for %s: %v", ad.ADCSESC6b.String(), err)
} else {
return nil
}

return nil
})
}
}

}
operation.Done()

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
return query.Kind(query.Relationship(), ad.ADCSESC6b)
})); err != nil {
t.Fatalf("error fetching esc6b edges in integration test; %v", err)
} else {
require.Equal(t, 2, len(results))

require.True(t, results.Contains(harness.ESC6bTemplate1Harness.Group1))
require.True(t, results.Contains(harness.ESC6bTemplate1Harness.Group1))

require.False(t, results.Contains(harness.ESC6bTemplate1Harness.Group3))
require.False(t, results.Contains(harness.ESC6bTemplate1Harness.Group4))
require.False(t, results.Contains(harness.ESC6bTemplate1Harness.Group5))

}

return nil
})
})

testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
harness.ESC6bECAHarness.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC6b eca")

groupExpansions, err := ad2.ExpandAllRDPLocalGroups(context.Background(), db)
require.Nil(t, err)
enterpriseCertAuthorities, err := ad2.FetchNodesByKind(context.Background(), db, ad.EnterpriseCA)
require.Nil(t, err)
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
require.Nil(t, err)
domains, err := ad2.FetchNodesByKind(context.Background(), db, ad.Domain)
require.Nil(t, err)

cache := ad2.NewADCSCache()
cache.BuildCache(context.Background(), db, enterpriseCertAuthorities, certTemplates)

for _, domain := range domains {
innerDomain := domain

for _, enterpriseCA := range enterpriseCertAuthorities {
if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
innerEnterpriseCA := enterpriseCA

operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
if err := ad2.PostADCSESC6b(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
t.Logf("failed post processing for %s: %v", ad.ADCSESC6b.String(), err)
} else {
return nil
}

return nil
})
}
}

}
operation.Done()

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
if results, err := ops.FetchStartNodes(
tx.Relationships().Filterf(func() graph.Criteria {
return query.Kind(query.Relationship(), ad.ADCSESC6b)
})); err != nil {
t.Fatalf("error fetching esc6b edges in integration test; %v", err)
} else {
require.Equal(t, 1, len(results))

require.True(t, results.Contains(harness.ESC6bECAHarness.Group0))
}

return nil
})
})

testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
harness.ESC6bPrincipalEdgesHarness.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC6b principal edges")

groupExpansions, err := ad2.ExpandAllRDPLocalGroups(context.Background(), db)
require.Nil(t, err)
enterpriseCertAuthorities, err := ad2.FetchNodesByKind(context.Background(), db, ad.EnterpriseCA)
require.Nil(t, err)
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
require.Nil(t, err)
domains, err := ad2.FetchNodesByKind(context.Background(), db, ad.Domain)
require.Nil(t, err)

cache := ad2.NewADCSCache()
cache.BuildCache(context.Background(), db, enterpriseCertAuthorities, certTemplates)

for _, domain := range domains {
innerDomain := domain

for _, enterpriseCA := range enterpriseCertAuthorities {
if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
innerEnterpriseCA := enterpriseCA

operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
if err := ad2.PostADCSESC6b(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
t.Logf("failed post processing for %s: %v", ad.ADCSESC6b.String(), err)
} else {
return nil
}

return nil
})
}
}

}
operation.Done()

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
return query.Kind(query.Relationship(), ad.ADCSESC6b)
})); err != nil {
t.Fatalf("error fetching esc6b edges in integration test; %v", err)
} else {
require.Equal(t, 2, len(results))

require.True(t, results.Contains(harness.ESC6bPrincipalEdgesHarness.Group1))
require.True(t, results.Contains(harness.ESC6bPrincipalEdgesHarness.Group2))

}
return nil
})
})

testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
harness.ESC6bTemplate2Harness.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC6b")

groupExpansions, err := ad2.ExpandAllRDPLocalGroups(context.Background(), db)
require.Nil(t, err)
enterpriseCertAuthorities, err := ad2.FetchNodesByKind(context.Background(), db, ad.EnterpriseCA)
require.Nil(t, err)
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
require.Nil(t, err)
domains, err := ad2.FetchNodesByKind(context.Background(), db, ad.Domain)
require.Nil(t, err)

cache := ad2.NewADCSCache()
cache.BuildCache(context.Background(), db, enterpriseCertAuthorities, certTemplates)

for _, domain := range domains {
innerDomain := domain

for _, enterpriseCA := range enterpriseCertAuthorities {
if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
innerEnterpriseCA := enterpriseCA

operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
if err := ad2.PostADCSESC6b(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
t.Logf("failed post processing for %s: %v", ad.ADCSESC6b.String(), err)
} else {
return nil
}

return nil
})
}
}

}
operation.Done()

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
return query.Kind(query.Relationship(), ad.ADCSESC6b)
})); err != nil {
t.Fatalf("error fetching esc6a edges in integration test; %v", err)
} else {
require.True(t, len(results) == 12)

require.True(t, results.Contains(harness.ESC6bTemplate2Harness.User1))
require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Computer1))
require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Group1))

require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Computer2))
require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Group2))

require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Computer3))
require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Group3))

require.True(t, results.Contains(harness.ESC6bTemplate2Harness.User4))
require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Computer4))
require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Group4))

require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Group5))

require.True(t, results.Contains(harness.ESC6bTemplate2Harness.Group6))

}
return nil
})
})

}

func FetchADCSPrereqs(db graph.Database) (impact.PathAggregator, []*graph.Node, []*graph.Node, []*graph.Node, ad2.ADCSCache, error) {
if expansions, err := ad2.ExpandAllRDPLocalGroups(context.Background(), db); err != nil {
return nil, nil, nil, nil, ad2.ADCSCache{}, err
Expand Down
Loading

0 comments on commit fee4256

Please sign in to comment.