Skip to content

Commit

Permalink
Modified edge probability calculator function signature
Browse files Browse the repository at this point in the history
  • Loading branch information
lkarlslund committed Oct 10, 2024
1 parent 8c04e35 commit 56ca6cd
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 85 deletions.
8 changes: 4 additions & 4 deletions modules/engine/edge.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var (
ErrEdgeNotFound = errors.New("edge not found")
)

type ProbabilityCalculatorFunction func(source, target *Object) Probability
type ProbabilityCalculatorFunction func(source, target *Object, edge EdgeBitmap) Probability

func (pm Edge) RegisterProbabilityCalculator(doCalc ProbabilityCalculatorFunction) Edge {
edgeInfos[pm].probability = doCalc
Expand All @@ -25,9 +25,9 @@ func (pm Edge) Describe(description string) Edge {
return pm
}

func (pm Edge) Probability(source, target *Object) Probability {
func (pm Edge) Probability(source, target *Object, edges EdgeBitmap) Probability {
if f := edgeInfos[pm].probability; f != nil {
return f(source, target)
return f(source, target, edges)
}

// default
Expand Down Expand Up @@ -388,7 +388,7 @@ func (m EdgeBitmap) MaxProbability(source, target *Object) Probability {
max := MINPROBABILITY
for i := 0; i < len(edgeInfos); i++ {
if m.IsSet(Edge(i)) {
prob := Edge(i).Probability(source, target)
prob := Edge(i).Probability(source, target, m)
if prob == MAXPROBABILITY {
return prob
}
Expand Down
88 changes: 38 additions & 50 deletions modules/integrations/activedirectory/adedges.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,37 @@ package activedirectory

import "github.com/lkarlslund/adalanche/modules/engine"

func NotAChance(source, target *engine.Object) engine.Probability {
func OnlyIfTargetAccountEnabled(source, target *engine.Object, edges engine.EdgeBitmap) engine.Probability {
if target.HasTag("account_enabled") || edges.IsSet(EdgeWriteUserAccountControl) {
return 100
}
return 0
}

func FixedProbability(probability int) engine.ProbabilityCalculatorFunction {
return func(source, target *engine.Object, edge engine.EdgeBitmap) engine.Probability {
return engine.Probability(probability)
}
}

var (
EdgeACLContainsDeny = engine.NewEdge("ACLContainsDeny").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 0 }).Tag("Informative")
EdgeResetPassword = engine.NewEdge("ResetPassword").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
if target.HasTag("account_active") {
return 100
}
return 0
}).Tag("Pivot")
EdgeReadPasswordId = engine.NewEdge("ReadPasswordId").SetDefault(false, false, false).RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
return 5
})
EdgeACLContainsDeny = engine.NewEdge("ACLContainsDeny").RegisterProbabilityCalculator(FixedProbability(0)).Tag("Informative")
EdgeResetPassword = engine.NewEdge("ResetPassword").RegisterProbabilityCalculator(OnlyIfTargetAccountEnabled).Tag("Pivot")
EdgeReadPasswordId = engine.NewEdge("ReadPasswordId").SetDefault(false, false, false).RegisterProbabilityCalculator(FixedProbability(5))
EdgeOwns = engine.NewEdge("Owns").Tag("Pivot")
EdgeGenericAll = engine.NewEdge("GenericAll").Tag("Informative")
EdgeWriteAll = engine.NewEdge("WriteAll").Tag("Informative").RegisterProbabilityCalculator(NotAChance)
EdgeWritePropertyAll = engine.NewEdge("WritePropertyAll").Tag("Informative").RegisterProbabilityCalculator(NotAChance)
EdgeWriteExtendedAll = engine.NewEdge("WriteExtendedAll").Tag("Informative").RegisterProbabilityCalculator(NotAChance)
EdgeWriteAll = engine.NewEdge("WriteAll").Tag("Informative").RegisterProbabilityCalculator(FixedProbability(0))
EdgeWritePropertyAll = engine.NewEdge("WritePropertyAll").Tag("Informative").RegisterProbabilityCalculator(FixedProbability(0))
EdgeWriteExtendedAll = engine.NewEdge("WriteExtendedAll").Tag("Informative").RegisterProbabilityCalculator(FixedProbability(0))
EdgeTakeOwnership = engine.NewEdge("TakeOwnership").Tag("Pivot")
EdgeWriteDACL = engine.NewEdge("WriteDACL").Tag("Pivot")
EdgeWriteSPN = engine.NewEdge("WriteSPN").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
EdgeWriteSPN = engine.NewEdge("WriteSPN").RegisterProbabilityCalculator(func(source, target *engine.Object, edges engine.EdgeBitmap) engine.Probability {
if target.HasTag("account_active") {
return 50
}
return 0
}).Tag("Pivot")
EdgeWriteValidatedSPN = engine.NewEdge("WriteValidatedSPN").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
EdgeWriteValidatedSPN = engine.NewEdge("WriteValidatedSPN").RegisterProbabilityCalculator(func(source, target *engine.Object, edges engine.EdgeBitmap) engine.Probability {
if target.HasTag("account_active") {
return 50
}
Expand All @@ -43,68 +45,54 @@ var (
EdgeAddSelfMember = engine.NewEdge("AddSelfMember").Tag("Pivot")
EdgeReadGMSAPassword = engine.NewEdge("ReadGMSAPassword").Tag("Pivot")
EdgeHasMSA = engine.NewEdge("HasMSA").Tag("Granted")
EdgeWriteUserAccountControl = engine.NewEdge("WriteUserAccountControl").Describe("Allows attacker to set ENABLE and set DONT_REQ_PREAUTH and then to do AS_REP Kerberoasting").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
EdgeWriteUserAccountControl = engine.NewEdge("WriteUserAccountControl").Describe("Allows attacker to set ENABLE and set DONT_REQ_PREAUTH and then to do AS_REP Kerberoasting").RegisterProbabilityCalculator(func(source, target *engine.Object, edges engine.EdgeBitmap) engine.Probability {
/*if uac, ok := target.AttrInt(activedirectory.UserAccountControl); ok && uac&0x0002 != 0 { //UAC_ACCOUNTDISABLE
// Account is disabled
return 0
}*/
return 50
}).Tag("Pivot")

EdgeWriteKeyCredentialLink = engine.NewEdge("WriteKeyCredentialLink").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
if uac, ok := target.AttrInt(UserAccountControl); ok && uac&0x0002 /*UAC_ACCOUNTDISABLE*/ != 0 {
// Account is disabled
var canenable bool
source.Edges(engine.Out).Range(func(key *engine.Object, value engine.EdgeBitmap) bool {
if key == target {
if value.IsSet(EdgeWriteUserAccountControl) {
canenable = true
return false
}
}
return true
})
if !canenable {
return 0
}
EdgeWriteKeyCredentialLink = engine.NewEdge("WriteKeyCredentialLink").RegisterProbabilityCalculator(func(source, target *engine.Object, edges engine.EdgeBitmap) engine.Probability {
if target.HasTag("account_enabled") || edges.IsSet(EdgeWriteUserAccountControl) {
return 100
}
return 100
return 0
}).Tag("Pivot")
EdgeWriteAttributeSecurityGUID = engine.NewEdge("WriteAttrSecurityGUID").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 0 }) // Only if you patch the DC, so this will actually never work
EdgeWriteAttributeSecurityGUID = engine.NewEdge("WriteAttrSecurityGUID").RegisterProbabilityCalculator(FixedProbability(0)) // Only if you patch the DC, so this will actually never work
EdgeSIDHistoryEquality = engine.NewEdge("SIDHistoryEquality").Tag("Pivot")
EdgeAllExtendedRights = engine.NewEdge("AllExtendedRights").Tag("Informative").RegisterProbabilityCalculator(NotAChance)
EdgeDSReplicationSyncronize = engine.NewEdge("DSReplSync").Tag("Granted").SetDefault(false, false, false).Tag("Granted").RegisterProbabilityCalculator(NotAChance)
EdgeDSReplicationGetChanges = engine.NewEdge("DSReplGetChngs").SetDefault(false, false, false).Tag("Granted").Tag("Granted").RegisterProbabilityCalculator(NotAChance)
EdgeDSReplicationGetChangesAll = engine.NewEdge("DSReplGetChngsAll").SetDefault(false, false, false).Tag("Granted").Tag("Granted").RegisterProbabilityCalculator(NotAChance)
EdgeDSReplicationGetChangesInFilteredSet = engine.NewEdge("DSReplGetChngsInFiltSet").SetDefault(false, false, false).Tag("Granted").Tag("Granted").RegisterProbabilityCalculator(NotAChance)
EdgeAllExtendedRights = engine.NewEdge("AllExtendedRights").Tag("Informative").RegisterProbabilityCalculator(FixedProbability(0))
EdgeDSReplicationSyncronize = engine.NewEdge("DSReplSync").Tag("Granted").SetDefault(false, false, false).Tag("Granted").RegisterProbabilityCalculator(FixedProbability(0))
EdgeDSReplicationGetChanges = engine.NewEdge("DSReplGetChngs").SetDefault(false, false, false).Tag("Granted").Tag("Granted").RegisterProbabilityCalculator(FixedProbability(0))
EdgeDSReplicationGetChangesAll = engine.NewEdge("DSReplGetChngsAll").SetDefault(false, false, false).Tag("Granted").Tag("Granted").RegisterProbabilityCalculator(FixedProbability(0))
EdgeDSReplicationGetChangesInFilteredSet = engine.NewEdge("DSReplGetChngsInFiltSet").SetDefault(false, false, false).Tag("Granted").Tag("Granted").RegisterProbabilityCalculator(FixedProbability(0))
EdgeCall = engine.NewEdge("Call").Describe("Call a service point")
EdgeControls = engine.NewEdge("Controls").Describe("Node controls a service point")
EdgeReadLAPSPassword = engine.NewEdge("ReadLAPSPassword").Tag("Pivot").Tag("Granted")
EdgeMemberOfGroup = engine.NewEdge("MemberOfGroup").Tag("Granted")
EdgeMemberOfGroupIndirect = engine.NewEdge("MemberOfGroupIndirect").SetDefault(false, false, false).Tag("Granted")
EdgeHasSPN = engine.NewEdge("HasSPN").Describe("Kerberoastable by requesting Kerberos service ticket against SPN and then bruteforcing the ticket").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
if target.HasTag("account_active") {
EdgeHasSPN = engine.NewEdge("HasSPN").Describe("Kerberoastable by requesting Kerberos service ticket against SPN and then bruteforcing the ticket").RegisterProbabilityCalculator(func(source, target *engine.Object, edges engine.EdgeBitmap) engine.Probability {
if target.HasTag("account_enabled") || edges.IsSet(EdgeWriteUserAccountControl) {
return 50
}
// Account is disabled
return 0
}).Tag("Pivot")
EdgeDontReqPreauth = engine.NewEdge("DontReqPreauth").Describe("Kerberoastable by AS-REP by requesting a TGT and then bruteforcing the ticket").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
if uac, ok := target.AttrInt(UserAccountControl); ok && uac&0x0002 /*UAC_ACCOUNTDISABLE*/ != 0 {
// Account is disabled
return 0
EdgeDontReqPreauth = engine.NewEdge("DontReqPreauth").Describe("Kerberoastable by AS-REP by requesting a TGT and then bruteforcing the ticket").RegisterProbabilityCalculator(func(source, target *engine.Object, edges engine.EdgeBitmap) engine.Probability {
if target.HasTag("account_enabled") || edges.IsSet(EdgeWriteUserAccountControl) {
return 50
}
return 50
return 0
}).Tag("Pivot")
EdgeOverwritesACL = engine.NewEdge("OverwritesACL")
EdgeAffectedByGPO = engine.NewEdge("AffectedByGPO").Tag("Granted").Tag("Pivot")
PartOfGPO = engine.NewEdge("PartOfGPO").Tag("Granted").Tag("Pivot")
EdgeLocalAdminRights = engine.NewEdge("AdminRights").Tag("Granted").Tag("Pivot")
EdgeLocalRDPRights = engine.NewEdge("RDPRights").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 30 }).Tag("Pivot")
EdgeLocalDCOMRights = engine.NewEdge("DCOMRights").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 50 }).Tag("Pivot")
EdgeLocalRDPRights = engine.NewEdge("RDPRights").RegisterProbabilityCalculator(FixedProbability(30)).Tag("Pivot")
EdgeLocalDCOMRights = engine.NewEdge("DCOMRights").RegisterProbabilityCalculator(FixedProbability(30)).Tag("Pivot")
EdgeScheduledTaskOnUNCPath = engine.NewEdge("SchedTaskOnUNCPath").Tag("Pivot")
EdgeMachineScript = engine.NewEdge("MachineScript").Tag("Pivot")
EdgeWriteAltSecurityIdentities = engine.NewEdge("WriteAltSecIdent").Tag("Pivot")
EdgeWriteAltSecurityIdentities = engine.NewEdge("WriteAltSecIdent").Tag("Pivot").RegisterProbabilityCalculator(OnlyIfTargetAccountEnabled)
EdgeWriteProfilePath = engine.NewEdge("WriteProfilePath").Tag("Pivot")
EdgeWriteScriptPath = engine.NewEdge("WriteScriptPath").Tag("Pivot")
EdgeCertificateEnroll = engine.NewEdge("CertificateEnroll").Tag("Granted")
Expand Down
4 changes: 1 addition & 3 deletions modules/integrations/activedirectory/analyze/analyze-ad.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ var (
MetaPasswordAge = engine.NewAttribute("passwordAge")
MetaLastLoginAge = engine.NewAttribute("lastLoginAge")

EdgeMachineAccount = engine.NewEdge("MachineAccount").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
return -1 // Just informative
}).Describe("Indicates this is the domain joined computer account belonging to the machine")
EdgeMachineAccount = engine.NewEdge("MachineAccount").RegisterProbabilityCalculator(activedirectory.FixedProbability(-1)).Describe("Indicates this is the domain joined computer account belonging to the machine")
)

var warnedgpos = make(map[string]struct{})
Expand Down
39 changes: 11 additions & 28 deletions modules/integrations/localmachine/analyze/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package analyze

import (
"github.com/lkarlslund/adalanche/modules/engine"
"github.com/lkarlslund/adalanche/modules/integrations/activedirectory"
"github.com/lkarlslund/adalanche/modules/windowssecurity"
)

Expand All @@ -13,31 +14,13 @@ var (
ServiceStart = engine.NewAttribute("serviceStart")
ServiceType = engine.NewAttribute("serviceType")

EdgeLocalAdminRights = engine.NewEdge("AdminRights").Tag("Granted")
EdgeLocalRDPRights = engine.NewEdge("RDPRights").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
var probability engine.Probability
/* ENDLESS LOOPS
target.Edges(engine.In).Range(func(potential *engine.Object, edge engine.EdgeBitmap) bool {
sid := potential.SID()
if sid.IsBlank() {
return true // continue
}
if sid == windowssecurity.InteractiveSID || sid == windowssecurity.RemoteInteractiveSID || sid == windowssecurity.AuthenticatedUsersSID || sid == windowssecurity.EveryoneSID {
probability = edge.MaxProbability(potential, target)
return false // break
}
return true
})*/
if probability < 30 {
probability = 30
}
return probability
}).Tag("Granted").Tag("Pivot")
EdgeLocalDCOMRights = engine.NewEdge("DCOMRights").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 50 }).Tag("Granted")
EdgeLocalSMSAdmins = engine.NewEdge("SMSAdmins").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 50 }).Tag("Granted")
EdgeLocalSessionLastDay = engine.NewEdge("SessionLastDay").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 80 }).Tag("Pivot")
EdgeLocalSessionLastWeek = engine.NewEdge("SessionLastWeek").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 55 }).Tag("Pivot")
EdgeLocalSessionLastMonth = engine.NewEdge("SessionLastMonth").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 30 }).Tag("Pivot")
EdgeLocalAdminRights = engine.NewEdge("AdminRights").Tag("Granted")
EdgeLocalRDPRights = engine.NewEdge("RDPRights").RegisterProbabilityCalculator(activedirectory.FixedProbability(30)).Tag("Granted").Tag("Pivot")
EdgeLocalDCOMRights = engine.NewEdge("DCOMRights").RegisterProbabilityCalculator(activedirectory.FixedProbability(30)).Tag("Granted")
EdgeLocalSMSAdmins = engine.NewEdge("SMSAdmins").RegisterProbabilityCalculator(activedirectory.FixedProbability(50)).Tag("Granted")
EdgeLocalSessionLastDay = engine.NewEdge("SessionLastDay").RegisterProbabilityCalculator(activedirectory.FixedProbability(80)).Tag("Pivot")
EdgeLocalSessionLastWeek = engine.NewEdge("SessionLastWeek").RegisterProbabilityCalculator(activedirectory.FixedProbability(55)).Tag("Pivot")
EdgeLocalSessionLastMonth = engine.NewEdge("SessionLastMonth").RegisterProbabilityCalculator(activedirectory.FixedProbability(30)).Tag("Pivot")
EdgeHasServiceAccountCredentials = engine.NewEdge("SvcAccntCreds").Tag("Pivot")
EdgeHasAutoAdminLogonCredentials = engine.NewEdge("AutoAdminLogonCreds").Tag("Pivot")
EdgeRunsExecutable = engine.NewEdge("RunsExecutable")
Expand All @@ -59,21 +42,21 @@ var (
EdgeSeAssignPrimaryToken = engine.NewEdge("SeAssignPrimaryToken").Tag("Pivot")
EdgeSeCreateToken = engine.NewEdge("SeCreateToken").Tag("Pivot")
EdgeSeDebug = engine.NewEdge("SeDebug").Tag("Pivot")
EdgeSeImpersonate = engine.NewEdge("SeImpersonate").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 20 }).Tag("Pivot")
EdgeSeImpersonate = engine.NewEdge("SeImpersonate").RegisterProbabilityCalculator(activedirectory.FixedProbability(20)).Tag("Pivot")
EdgeSeLoadDriver = engine.NewEdge("SeLoadDriver").Tag("Pivot")
EdgeSeManageVolume = engine.NewEdge("SeManageVolume").Tag("Pivot")
EdgeSeTakeOwnership = engine.NewEdge("SeTakeOwnership").Tag("Pivot")
EdgeSeTrustedCredManAccess = engine.NewEdge("SeTrustedCredManAccess").Tag("Pivot")
EdgeSeTcb = engine.NewEdge("SeTcb").Tag("Pivot")

EdgeSeNetworkLogonRight = engine.NewEdge("SeNetworkLogonRight").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 10 })
EdgeSeNetworkLogonRight = engine.NewEdge("SeNetworkLogonRight").RegisterProbabilityCalculator(activedirectory.FixedProbability(10))
// RDPRight used ... EdgeSeRemoteInteractiveLogonRight = engine.NewEdge("SeRemoteInteractiveLogonRight").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 10 })

// SeDenyNetworkLogonRight
// SeDenyInteractiveLogonRight
// SeDenyRemoteInteractiveLogonRight

EdgeSIDCollision = engine.NewEdge("SIDCollision").Tag("Informative").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability { return 0 })
EdgeSIDCollision = engine.NewEdge("SIDCollision").Tag("Informative").RegisterProbabilityCalculator(activedirectory.FixedProbability(0))

DNSHostname = engine.NewAttribute("dnsHostName")
EdgeControlsUpdates = engine.NewEdge("ControlsUpdates").Tag("Affects")
Expand Down

0 comments on commit 56ca6cd

Please sign in to comment.