Skip to content

Commit 16dfc6d

Browse files
authored
Merge pull request #4 from joreiche/pr-18-transfer
Stored, sent and received data assets are always processed
2 parents a7a61c6 + 033fc8a commit 16dfc6d

27 files changed

+100
-105
lines changed

cmd/raa/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,14 @@ func calculateAttackerAttractiveness(input *types.ParsedModel, techAsset types.T
167167
score += dataAsset.Integrity.AttackerAttractivenessForProcessedOrStoredData() * dataAsset.Quantity.QuantityFactor()
168168
score += dataAsset.Availability.AttackerAttractivenessForProcessedOrStoredData()
169169
}
170+
// NOTE: Assuming all stored data is also processed, this effectively scores stored data twice
170171
for _, dataAssetStored := range techAsset.DataAssetsStored {
171172
dataAsset := input.DataAssets[dataAssetStored]
172173
score += dataAsset.Confidentiality.AttackerAttractivenessForProcessedOrStoredData() * dataAsset.Quantity.QuantityFactor()
173174
score += dataAsset.Integrity.AttackerAttractivenessForProcessedOrStoredData() * dataAsset.Quantity.QuantityFactor()
174175
score += dataAsset.Availability.AttackerAttractivenessForProcessedOrStoredData()
175176
}
177+
// NOTE: To send or receive data effectively is processing that data and it's questionable if the attractiveness increases further
176178
for _, dataFlow := range techAsset.CommunicationLinks {
177179
for _, dataAssetSent := range dataFlow.DataAssetsSent {
178180
dataAsset := input.DataAssets[dataAssetSent]

pkg/model/parse.go

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,29 +129,35 @@ func ParseModel(modelInput *input.Model, builtinRiskRules map[string]risks.RiskR
129129
return nil, errors.New("unknown 'usage' value of technical asset '" + title + "': " + asset.Usage)
130130
}
131131

132-
var dataAssetsProcessed = make([]string, 0)
133-
if asset.DataAssetsProcessed != nil {
134-
dataAssetsProcessed = make([]string, len(asset.DataAssetsProcessed))
135-
for i, parsedProcessedAsset := range asset.DataAssetsProcessed {
136-
referencedAsset := fmt.Sprintf("%v", parsedProcessedAsset)
132+
var dataAssetsStored = make([]string, 0)
133+
if asset.DataAssetsStored != nil {
134+
for _, parsedStoredAssets := range asset.DataAssetsStored {
135+
referencedAsset := fmt.Sprintf("%v", parsedStoredAssets)
136+
if contains(dataAssetsStored, referencedAsset) {
137+
continue
138+
}
139+
137140
err := parsedModel.CheckDataAssetTargetExists(referencedAsset, "technical asset '"+title+"'")
138141
if err != nil {
139142
return nil, err
140143
}
141-
dataAssetsProcessed[i] = referencedAsset
144+
dataAssetsStored = append(dataAssetsStored, referencedAsset)
142145
}
143146
}
144147

145-
var dataAssetsStored = make([]string, 0)
146-
if asset.DataAssetsStored != nil {
147-
dataAssetsStored = make([]string, len(asset.DataAssetsStored))
148-
for i, parsedStoredAssets := range asset.DataAssetsStored {
149-
referencedAsset := fmt.Sprintf("%v", parsedStoredAssets)
148+
var dataAssetsProcessed = dataAssetsStored
149+
if asset.DataAssetsProcessed != nil {
150+
for _, parsedProcessedAsset := range asset.DataAssetsProcessed {
151+
referencedAsset := fmt.Sprintf("%v", parsedProcessedAsset)
152+
if contains(dataAssetsProcessed, referencedAsset) {
153+
continue
154+
}
155+
150156
err := parsedModel.CheckDataAssetTargetExists(referencedAsset, "technical asset '"+title+"'")
151157
if err != nil {
152158
return nil, err
153159
}
154-
dataAssetsStored[i] = referencedAsset
160+
dataAssetsProcessed = append(dataAssetsProcessed, referencedAsset)
155161
}
156162
}
157163

@@ -227,22 +233,36 @@ func ParseModel(modelInput *input.Model, builtinRiskRules map[string]risks.RiskR
227233
if commLink.DataAssetsSent != nil {
228234
for _, dataAssetSent := range commLink.DataAssetsSent {
229235
referencedAsset := fmt.Sprintf("%v", dataAssetSent)
230-
err := parsedModel.CheckDataAssetTargetExists(referencedAsset, "communication link '"+commLinkTitle+"' of technical asset '"+title+"'")
231-
if err != nil {
232-
return nil, err
236+
if !contains(dataAssetsSent, referencedAsset) {
237+
err := parsedModel.CheckDataAssetTargetExists(referencedAsset, "communication link '"+commLinkTitle+"' of technical asset '"+title+"'")
238+
if err != nil {
239+
return nil, err
240+
}
241+
242+
dataAssetsSent = append(dataAssetsSent, referencedAsset)
243+
if !contains(dataAssetsProcessed, referencedAsset) {
244+
dataAssetsProcessed = append(dataAssetsProcessed, referencedAsset)
245+
}
233246
}
234-
dataAssetsSent = append(dataAssetsSent, referencedAsset)
235247
}
236248
}
237249

238250
if commLink.DataAssetsReceived != nil {
239251
for _, dataAssetReceived := range commLink.DataAssetsReceived {
240252
referencedAsset := fmt.Sprintf("%v", dataAssetReceived)
253+
if contains(dataAssetsReceived, referencedAsset) {
254+
continue
255+
}
256+
241257
err := parsedModel.CheckDataAssetTargetExists(referencedAsset, "communication link '"+commLinkTitle+"' of technical asset '"+title+"'")
242258
if err != nil {
243259
return nil, err
244260
}
245261
dataAssetsReceived = append(dataAssetsReceived, referencedAsset)
262+
263+
if !contains(dataAssetsProcessed, referencedAsset) {
264+
dataAssetsProcessed = append(dataAssetsProcessed, referencedAsset)
265+
}
246266
}
247267
}
248268

@@ -334,6 +354,29 @@ func ParseModel(modelInput *input.Model, builtinRiskRules map[string]risks.RiskR
334354
}
335355
}
336356

357+
// A target of a communication link implicitly processes all data assets that are sent to or received by that target
358+
for id, techAsset := range parsedModel.TechnicalAssets {
359+
for _, commLink := range techAsset.CommunicationLinks {
360+
if commLink.TargetId == id {
361+
continue
362+
}
363+
targetTechAsset := parsedModel.TechnicalAssets[commLink.TargetId]
364+
dataAssetsProcessedByTarget := targetTechAsset.DataAssetsProcessed
365+
for _, dataAssetSent := range commLink.DataAssetsSent {
366+
if !contains(dataAssetsProcessedByTarget, dataAssetSent) {
367+
dataAssetsProcessedByTarget = append(dataAssetsProcessedByTarget, dataAssetSent)
368+
}
369+
}
370+
for _, dataAssetReceived := range commLink.DataAssetsReceived {
371+
if !contains(dataAssetsProcessedByTarget, dataAssetReceived) {
372+
dataAssetsProcessedByTarget = append(dataAssetsProcessedByTarget, dataAssetReceived)
373+
}
374+
}
375+
targetTechAsset.DataAssetsProcessed = dataAssetsProcessedByTarget
376+
parsedModel.TechnicalAssets[commLink.TargetId] = targetTechAsset
377+
}
378+
}
379+
337380
// Trust Boundaries ===============================================================================
338381
checklistToAvoidAssetBeingModeledInMultipleTrustBoundaries := make(map[string]bool)
339382
parsedModel.TrustBoundaries = make(map[string]types.TrustBoundary)
@@ -713,3 +756,12 @@ func lowerCaseAndTrim(tags []string) []string {
713756
}
714757
return tags
715758
}
759+
760+
func contains(a []string, x string) bool {
761+
for _, n := range a {
762+
if x == n {
763+
return true
764+
}
765+
}
766+
return false
767+
}

pkg/report/colors.go

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -367,18 +367,12 @@ func determineTechnicalAssetLabelColor(ta types.TechnicalAsset, model *types.Par
367367

368368
// red when mission-critical integrity, but still unauthenticated (non-readonly) channels access it
369369
// amber when critical integrity, but still unauthenticated (non-readonly) channels access it
370-
// pink when model forgery attempt (i.e. nothing being processed or stored)
371-
370+
// pink when model forgery attempt (i.e. nothing being processed)
372371
func determineShapeBorderColor(ta types.TechnicalAsset, parsedModel *types.ParsedModel) string {
373372
// Check for red
374373
if ta.Confidentiality == types.StrictlyConfidential {
375374
return Red
376375
}
377-
for _, storedDataAsset := range ta.DataAssetsStored {
378-
if parsedModel.DataAssets[storedDataAsset].Confidentiality == types.StrictlyConfidential {
379-
return Red
380-
}
381-
}
382376
for _, processedDataAsset := range ta.DataAssetsProcessed {
383377
if parsedModel.DataAssets[processedDataAsset].Confidentiality == types.StrictlyConfidential {
384378
return Red
@@ -388,11 +382,6 @@ func determineShapeBorderColor(ta types.TechnicalAsset, parsedModel *types.Parse
388382
if ta.Confidentiality == types.Confidential {
389383
return Amber
390384
}
391-
for _, storedDataAsset := range ta.DataAssetsStored {
392-
if parsedModel.DataAssets[storedDataAsset].Confidentiality == types.Confidential {
393-
return Amber
394-
}
395-
}
396385
for _, processedDataAsset := range ta.DataAssetsProcessed {
397386
if parsedModel.DataAssets[processedDataAsset].Confidentiality == types.Confidential {
398387
return Amber
@@ -427,7 +416,7 @@ func determineShapeBorderColor(ta types.TechnicalAsset, parsedModel *types.Parse
427416
// dotted when model forgery attempt (i.e. nothing being processed or stored)
428417

429418
func determineShapeBorderLineStyle(ta types.TechnicalAsset) string {
430-
if len(ta.DataAssetsProcessed) == 0 && len(ta.DataAssetsStored) == 0 || ta.OutOfScope {
419+
if len(ta.DataAssetsProcessed) == 0 || ta.OutOfScope {
431420
return "dotted" // dotted, because it's strange when too many technical communication links transfer no data... some ok, but many in a diagram ist a sign of model forgery...
432421
}
433422
return "solid"

pkg/security/risks/builtin/accidental-secret-leak-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func (*AccidentalSecretLeakRule) Category() types.RiskCategory {
2929
Function: types.Operations,
3030
STRIDE: types.InformationDisclosure,
3131
DetectionLogic: "In-scope sourcecode repositories and artifact registries.",
32-
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed and stored.",
32+
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed.",
3333
FalsePositives: "Usually no false positives.",
3434
ModelFailurePossibleReason: false,
3535
CWE: 200,

pkg/security/risks/builtin/container-platform-escape-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (*ContainerPlatformEscapeRule) Category() types.RiskCategory {
3434
Function: types.Operations,
3535
STRIDE: types.ElevationOfPrivilege,
3636
DetectionLogic: "In-scope container platforms.",
37-
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed and stored.",
37+
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed.",
3838
FalsePositives: "Container platforms not running parts of the target architecture can be considered " +
3939
"as false positives after individual review.",
4040
ModelFailurePossibleReason: false,

pkg/security/risks/builtin/cross-site-scripting-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (*CrossSiteScriptingRule) Category() types.RiskCategory {
2727
Function: types.Development,
2828
STRIDE: types.Tampering,
2929
DetectionLogic: "In-scope web applications.",
30-
RiskAssessment: "The risk rating depends on the sensitivity of the data processed or stored in the web application.",
30+
RiskAssessment: "The risk rating depends on the sensitivity of the data processed in the web application.",
3131
FalsePositives: "When the technical asset " +
3232
"is not accessed via a browser-like component (i.e not by a human user initiating the request that " +
3333
"gets passed through all components until it reaches the web application) this can be considered a false positive.",

pkg/security/risks/builtin/ldap-injection-rule.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func (*LdapInjectionRule) Category() types.RiskCategory {
1515
Id: "ldap-injection",
1616
Title: "LDAP-Injection",
1717
Description: "When an LDAP server is accessed LDAP-Injection risks might arise. " +
18-
"The risk rating depends on the sensitivity of the LDAP server itself and of the data assets processed or stored.",
18+
"The risk rating depends on the sensitivity of the LDAP server itself and of the data assets processed.",
1919
Impact: "If this risk remains unmitigated, attackers might be able to modify LDAP queries and access more data from the LDAP server than allowed.",
2020
ASVS: "V5 - Validation, Sanitization and Encoding Verification Requirements",
2121
CheatSheet: "https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html",
@@ -27,7 +27,7 @@ func (*LdapInjectionRule) Category() types.RiskCategory {
2727
Function: types.Development,
2828
STRIDE: types.Tampering,
2929
DetectionLogic: "In-scope clients accessing LDAP servers via typical LDAP access protocols.",
30-
RiskAssessment: "The risk rating depends on the sensitivity of the LDAP server itself and of the data assets processed or stored.",
30+
RiskAssessment: "The risk rating depends on the sensitivity of the LDAP server itself and of the data assets processed.",
3131
FalsePositives: "LDAP server queries by search values not consisting of parts controllable by the caller can be considered " +
3232
"as false positives after individual review.",
3333
ModelFailurePossibleReason: false,

pkg/security/risks/builtin/missing-authentication-rule.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func (*MissingAuthenticationRule) Category() types.RiskCategory {
1414
return types.RiskCategory{
1515
Id: "missing-authentication",
1616
Title: "Missing Authentication",
17-
Description: "Technical assets (especially multi-tenant systems) should authenticate incoming requests when the asset processes or stores sensitive data. ",
17+
Description: "Technical assets (especially multi-tenant systems) should authenticate incoming requests when the asset processes sensitive data. ",
1818
Impact: "If this risk is unmitigated, attackers might be able to access or modify sensitive data in an unauthenticated way.",
1919
ASVS: "V2 - Authentication Verification Requirements",
2020
CheatSheet: "https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html",
@@ -24,7 +24,7 @@ func (*MissingAuthenticationRule) Category() types.RiskCategory {
2424
Check: "Are recommendations from the linked cheat sheet and referenced ASVS chapter applied?",
2525
Function: types.Architecture,
2626
STRIDE: types.ElevationOfPrivilege,
27-
DetectionLogic: "In-scope technical assets (except " + types.LoadBalancer.String() + ", " + types.ReverseProxy.String() + ", " + types.ServiceRegistry.String() + ", " + types.WAF.String() + ", " + types.IDS.String() + ", and " + types.IPS.String() + " and in-process calls) should authenticate incoming requests when the asset processes or stores " +
27+
DetectionLogic: "In-scope technical assets (except " + types.LoadBalancer.String() + ", " + types.ReverseProxy.String() + ", " + types.ServiceRegistry.String() + ", " + types.WAF.String() + ", " + types.IDS.String() + ", and " + types.IPS.String() + " and in-process calls) should authenticate incoming requests when the asset processes " +
2828
"sensitive data. This is especially the case for all multi-tenant assets (there even non-sensitive ones).",
2929
RiskAssessment: "The risk rating (medium or high) " +
3030
"depends on the sensitivity of the data sent across the communication link. Monitoring callers are exempted from this risk.",

pkg/security/risks/builtin/missing-cloud-hardening-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (*MissingCloudHardeningRule) Category() types.RiskCategory {
3535
Function: types.Operations,
3636
STRIDE: types.Tampering,
3737
DetectionLogic: "In-scope cloud components (either residing in cloud trust boundaries or more specifically tagged with cloud provider types).",
38-
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed and stored.",
38+
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed.",
3939
FalsePositives: "Cloud components not running parts of the target architecture can be considered " +
4040
"as false positives after individual review.",
4141
ModelFailurePossibleReason: false,

pkg/security/risks/builtin/missing-file-validation-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (*MissingFileValidationRule) Category() types.RiskCategory {
2828
Function: types.Development,
2929
STRIDE: types.Spoofing,
3030
DetectionLogic: "In-scope technical assets with custom-developed code accepting file data formats.",
31-
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed and stored.",
31+
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed.",
3232
FalsePositives: "Fully trusted (i.e. cryptographically signed or similar) files can be considered " +
3333
"as false positives after individual review.",
3434
ModelFailurePossibleReason: false,

pkg/security/risks/builtin/missing-hardening-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (r *MissingHardeningRule) Category() types.RiskCategory {
3232
STRIDE: types.Tampering,
3333
DetectionLogic: "In-scope technical assets with RAA values of " + strconv.Itoa(r.raaLimit) + " % or higher. " +
3434
"Generally for high-value targets like data stores, application servers, identity providers and ERP systems this limit is reduced to " + strconv.Itoa(r.raaLimitReduced) + " %",
35-
RiskAssessment: "The risk rating depends on the sensitivity of the data processed or stored in the technical asset.",
35+
RiskAssessment: "The risk rating depends on the sensitivity of the data processed in the technical asset.",
3636
FalsePositives: "Usually no false positives.",
3737
ModelFailurePossibleReason: false,
3838
CWE: 16,

pkg/security/risks/builtin/missing-identity-store-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (*MissingIdentityStoreRule) Category() types.RiskCategory {
2727
STRIDE: types.Spoofing,
2828
DetectionLogic: "Models with authenticated data-flows authorized via end user identity missing an in-scope identity store.",
2929
RiskAssessment: "The risk rating depends on the sensitivity of the end user-identity authorized technical assets and " +
30-
"their data assets processed and stored.",
30+
"their data assets processed.",
3131
FalsePositives: "Models only offering data/services without any real authentication need " +
3232
"can be considered as false positives after individual review.",
3333
ModelFailurePossibleReason: true,

pkg/security/risks/builtin/missing-vault-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (*MissingVaultRule) Category() types.RiskCategory {
2828
Function: types.Architecture,
2929
STRIDE: types.InformationDisclosure,
3030
DetectionLogic: "Models without a Vault (Secret Storage).",
31-
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed and stored.",
31+
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed.",
3232
FalsePositives: "Models where no technical assets have any kind of sensitive config data to protect " +
3333
"can be considered as false positives after individual review.",
3434
ModelFailurePossibleReason: true,

pkg/security/risks/builtin/missing-waf-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (*MissingWafRule) Category() types.RiskCategory {
2727
Function: types.Operations,
2828
STRIDE: types.Tampering,
2929
DetectionLogic: "In-scope web-services and/or web-applications accessed across a network trust boundary not having a Web Application Firewall (WAF) in front of them.",
30-
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed and stored.",
30+
RiskAssessment: "The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed.",
3131
FalsePositives: "Targets only accessible via WAFs or reverse proxies containing a WAF component (like ModSecurity) can be considered " +
3232
"as false positives after individual review.",
3333
ModelFailurePossibleReason: false,

pkg/security/risks/builtin/path-traversal-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func (*PathTraversalRule) Category() types.RiskCategory {
1515
Id: "path-traversal",
1616
Title: "Path-Traversal",
1717
Description: "When a filesystem is accessed Path-Traversal or Local-File-Inclusion (LFI) risks might arise. " +
18-
"The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed or stored.",
18+
"The risk rating depends on the sensitivity of the technical asset itself and of the data assets processed.",
1919
Impact: "If this risk is unmitigated, attackers might be able to read sensitive files (configuration data, key/credential files, deployment files, " +
2020
"business data files, etc.) from the filesystem of affected components.",
2121
ASVS: "V12 - File and Resources Verification Requirements",

pkg/security/risks/builtin/search-query-injection-rule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (*SearchQueryInjectionRule) Category() types.RiskCategory {
3030
Function: types.Development,
3131
STRIDE: types.Tampering,
3232
DetectionLogic: "In-scope clients accessing search engine servers via typical search access protocols.",
33-
RiskAssessment: "The risk rating depends on the sensitivity of the search engine server itself and of the data assets processed or stored.",
33+
RiskAssessment: "The risk rating depends on the sensitivity of the search engine server itself and of the data assets processed.",
3434
FalsePositives: "Server engine queries by search values not consisting of parts controllable by the caller can be considered " +
3535
"as false positives after individual review.",
3636
ModelFailurePossibleReason: false,

0 commit comments

Comments
 (0)