diff --git a/modules/engine/edge.go b/modules/engine/edge.go index 2cacb0c..79b856f 100644 --- a/modules/engine/edge.go +++ b/modules/engine/edge.go @@ -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 @@ -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 @@ -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 } diff --git a/modules/integrations/activedirectory/adedges.go b/modules/integrations/activedirectory/adedges.go index 32394bd..deca586 100644 --- a/modules/integrations/activedirectory/adedges.go +++ b/modules/integrations/activedirectory/adedges.go @@ -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 } @@ -43,7 +45,7 @@ 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 @@ -51,60 +53,46 @@ var ( 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") diff --git a/modules/integrations/activedirectory/analyze/analyze-ad.go b/modules/integrations/activedirectory/analyze/analyze-ad.go index 799af40..ced18de 100644 --- a/modules/integrations/activedirectory/analyze/analyze-ad.go +++ b/modules/integrations/activedirectory/analyze/analyze-ad.go @@ -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{}) diff --git a/modules/integrations/localmachine/analyze/analyzer.go b/modules/integrations/localmachine/analyze/analyzer.go index 2b4e2ab..03c7161 100644 --- a/modules/integrations/localmachine/analyze/analyzer.go +++ b/modules/integrations/localmachine/analyze/analyzer.go @@ -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" ) @@ -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") @@ -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")