-
Notifications
You must be signed in to change notification settings - Fork 124
/
missing-identity-store-rule.go
95 lines (90 loc) · 4.24 KB
/
missing-identity-store-rule.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package missing_identity_store
import (
"github.com/threagile/threagile/model"
)
func Category() model.RiskCategory {
return model.RiskCategory{
Id: "missing-identity-store",
Title: "Missing Identity Store",
Description: "The modeled architecture does not contain an identity store, which might be the risk of a model missing " +
"critical assets (and thus not seeing their risks).",
Impact: "If this risk is unmitigated, attackers might be able to exploit risks unseen in this threat model in the identity provider/store " +
"that is currently missing in the model.",
ASVS: "V2 - Authentication Verification Requirements",
CheatSheet: "https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html",
Action: "Identity Store",
Mitigation: "Include an identity store in the model if the application has a login.",
Check: "Are recommendations from the linked cheat sheet and referenced ASVS chapter applied?",
Function: model.Architecture,
STRIDE: model.Spoofing,
DetectionLogic: "Models with authenticated data-flows authorized via enduser-identity missing an in-scope identity store.",
RiskAssessment: "The risk rating depends on the sensitivity of the enduser-identity authorized technical assets and " +
"their data assets processed and stored.",
FalsePositives: "Models only offering data/services without any real authentication need " +
"can be considered as false positives after individual review.",
ModelFailurePossibleReason: true,
CWE: 287,
}
}
func SupportedTags() []string {
return []string{}
}
func GenerateRisks() []model.Risk {
risks := make([]model.Risk, 0)
for _, technicalAsset := range model.ParsedModelRoot.TechnicalAssets {
if !technicalAsset.OutOfScope &&
(technicalAsset.Technology == model.IdentityStoreLDAP || technicalAsset.Technology == model.IdentityStoreDatabase) {
// everything fine, no risk, as we have an in-scope identity store in the model
return risks
}
}
// now check if we have enduser-identity authorized communication links, then it's a risk
riskIdentified := false
var mostRelevantAsset model.TechnicalAsset
impact := model.LowImpact
for _, id := range model.SortedTechnicalAssetIDs() { // use the sorted one to always get the same tech asset with highest sensitivity as example asset
technicalAsset := model.ParsedModelRoot.TechnicalAssets[id]
for _, commLink := range technicalAsset.CommunicationLinksSorted() { // use the sorted one to always get the same tech asset with highest sensitivity as example asset
if commLink.Authorization == model.EnduserIdentityPropagation {
riskIdentified = true
targetAsset := model.ParsedModelRoot.TechnicalAssets[commLink.TargetId]
if impact == model.LowImpact {
mostRelevantAsset = targetAsset
if targetAsset.HighestConfidentiality() >= model.Confidential ||
targetAsset.HighestIntegrity() >= model.Critical ||
targetAsset.HighestAvailability() >= model.Critical {
impact = model.MediumImpact
}
}
if targetAsset.Confidentiality >= model.Confidential ||
targetAsset.Integrity >= model.Critical ||
targetAsset.Availability >= model.Critical {
impact = model.MediumImpact
}
// just for referencing the most interesting asset
if technicalAsset.HighestSensitivityScore() > mostRelevantAsset.HighestSensitivityScore() {
mostRelevantAsset = technicalAsset
}
}
}
}
if riskIdentified {
risks = append(risks, createRisk(mostRelevantAsset, impact))
}
return risks
}
func createRisk(technicalAsset model.TechnicalAsset, impact model.RiskExploitationImpact) model.Risk {
title := "<b>Missing Identity Store</b> in the threat model (referencing asset <b>" + technicalAsset.Title + "</b> as an example)"
risk := model.Risk{
Category: Category(),
Severity: model.CalculateSeverity(model.Unlikely, impact),
ExploitationLikelihood: model.Unlikely,
ExploitationImpact: impact,
Title: title,
MostRelevantTechnicalAssetId: technicalAsset.Id,
DataBreachProbability: model.Improbable,
DataBreachTechnicalAssetIDs: []string{},
}
risk.SyntheticId = risk.Category.Id + "@" + technicalAsset.Id
return risk
}