Skip to content

Commit d8066e7

Browse files
Merge pull request #322 from org-metaeffekt/ae-1607-display-cwes-in-advisory
AE-1607: CWE/CAPEC: Mirrored changes from artifact analysis
2 parents f35dd7c + 9a8cd78 commit d8066e7

File tree

6 files changed

+223
-141
lines changed

6 files changed

+223
-141
lines changed

libraries/ae-inventory-processor/src/main/java/org/metaeffekt/core/inventory/processor/report/model/aeaa/AeaaMatchableDetailsAmbDataClass.java

Lines changed: 173 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
*/
1616
package org.metaeffekt.core.inventory.processor.report.model.aeaa;
1717

18+
import lombok.Getter;
1819
import org.json.JSONArray;
1920
import org.json.JSONObject;
2021
import org.metaeffekt.core.inventory.processor.model.AbstractModelBase;
2122
import org.metaeffekt.core.inventory.processor.model.AdvisoryMetaData;
2223
import org.metaeffekt.core.inventory.processor.model.Artifact;
2324
import org.metaeffekt.core.inventory.processor.model.VulnerabilityMetaData;
2425
import org.metaeffekt.core.inventory.processor.report.model.aeaa.advisory.AeaaAdvisoryEntry;
26+
import org.metaeffekt.core.inventory.processor.report.model.aeaa.mitre.AeaaCapecEntry;
27+
import org.metaeffekt.core.inventory.processor.report.model.aeaa.mitre.AeaaCweEntry;
2528
import org.metaeffekt.core.inventory.processor.report.model.aeaa.store.*;
2629
import org.slf4j.Logger;
2730
import org.slf4j.LoggerFactory;
@@ -46,21 +49,23 @@ public abstract class AeaaMatchableDetailsAmbDataClass<AMB extends AbstractModel
4649
add(AdvisoryMetaData.Attribute.REFERENCED_VULNERABILITIES.getKey());
4750
add(VulnerabilityMetaData.Attribute.REFERENCED_VULNERABILITIES.getKey());
4851
add(AdvisoryMetaData.Attribute.REFERENCED_OTHER.getKey());
52+
add(VulnerabilityMetaData.Attribute.WEAKNESS.getKey());
53+
add(VulnerabilityMetaData.Attribute.WEAKNESS_DATA.getKey());
54+
add(VulnerabilityMetaData.Attribute.CAPEC_DATA.getKey());
4955
add(VulnerabilityMetaData.Attribute.REFERENCED_OTHER.getKey());
5056

5157
add(AeaaInventoryAttribute.RETAINED_VULNERABLE_SOFTWARE_CONFIGURATIONS.getKey());
5258
}};
5359

5460
protected final static Set<String> CONVERSION_KEYS_MAP = new HashSet<String>(AeaaAmbDataClass.CONVERSION_KEYS_MAP) {{
55-
add("source");
56-
add("sourceImplementation");
57-
add("dataFillingSources");
58-
add("matchingSources");
59-
add("referencedIds");
60-
add("referencedSecurityAdvisories");
61-
add("referencedVulnerabilities");
62-
add("referencedOtherIds");
63-
add("retainedVulnerableSoftwareConfigurations");
61+
addAll(Arrays.asList(
62+
"source", "sourceImplementation",
63+
"dataFillingSources", "matchingSources",
64+
"referencedIds", // legacy property
65+
"referencedSecurityAdvisories", "referencedVulnerabilities", "referencedOtherIds",
66+
"cwe", "cweData", "capecData",
67+
"retainedVulnerableSoftwareConfigurations"
68+
));
6469
}};
6570

6671
protected final Map<AeaaVulnerabilityTypeIdentifier<?>, Set<String>> referencedVulnerabilities = new HashMap<>();
@@ -80,8 +85,77 @@ public abstract class AeaaMatchableDetailsAmbDataClass<AMB extends AbstractModel
8085
*/
8186
protected final Map<String, Set<Artifact>> affectedArtifacts = new HashMap<>();
8287

88+
@Getter
89+
protected final List<AeaaCweEntry> weaknesses = new ArrayList<>();
90+
@Getter
91+
protected final List<AeaaCapecEntry> attackPatterns = new ArrayList<>();
92+
8393
public abstract AeaaContentIdentifierStore.AeaaContentIdentifier getSourceIdentifier();
8494

95+
public void addWeakness(String id) {
96+
if (StringUtils.hasText(id)) this.addWeakness(new AeaaCweEntry(id));
97+
}
98+
99+
public void addWeakness(Collection<String> ids) {
100+
ids.forEach(this::addWeakness);
101+
}
102+
103+
public Set<String> getWeaknessIds() {
104+
return getWeaknesses().stream().map(AeaaCweEntry::getId).collect(Collectors.toSet());
105+
}
106+
107+
public void addWeakness(AeaaCweEntry weakness) {
108+
if (weakness == null) return;
109+
110+
final AeaaCweEntry knownWeakness = findWeakness(weakness.getId());
111+
if (knownWeakness == null) {
112+
weaknesses.add(weakness);
113+
} else {
114+
if (StringUtils.isEmpty(knownWeakness.getName())) {
115+
weaknesses.remove(knownWeakness);
116+
weaknesses.add(weakness);
117+
}
118+
}
119+
120+
this.addOtherReferencedId(AeaaOtherTypeStore.CWE, weakness.getId());
121+
}
122+
123+
public AeaaCweEntry findWeakness(String id) {
124+
return this.weaknesses.stream()
125+
.filter(c -> c.getId().equals(id))
126+
.findFirst().orElse(null);
127+
}
128+
129+
public void addAttackPattern(String id) {
130+
if (StringUtils.hasText(id)) this.addAttackPattern(new AeaaCapecEntry(id));
131+
}
132+
133+
public void addAttackPattern(AeaaCapecEntry attackPattern) {
134+
if (attackPattern == null) return;
135+
136+
final AeaaCapecEntry knownAttackPattern = findAttackPattern(attackPattern.getId());
137+
if (knownAttackPattern == null) {
138+
attackPatterns.add(attackPattern);
139+
} else {
140+
if (StringUtils.isEmpty(knownAttackPattern.getName())) {
141+
attackPatterns.remove(knownAttackPattern);
142+
attackPatterns.add(attackPattern);
143+
}
144+
}
145+
146+
this.addOtherReferencedId(AeaaOtherTypeStore.CAPEC, attackPattern.getId());
147+
}
148+
149+
public Set<String> getAttackPatternIds() {
150+
return getAttackPatterns().stream().map(AeaaCapecEntry::getId).collect(Collectors.toSet());
151+
}
152+
153+
public AeaaCapecEntry findAttackPattern(String id) {
154+
return this.attackPatterns.stream()
155+
.filter(c -> c.getId().equals(id))
156+
.findFirst().orElse(null);
157+
}
158+
85159
public DC addMatchingSource(AeaaDataSourceIndicator matchingSource) {
86160
try {
87161
this.matchingSources.add(matchingSource);
@@ -189,18 +263,7 @@ public DC removeAffectsArtifact(String key, Artifact artifact) {
189263
return (DC) this;
190264
}
191265

192-
public Map<AeaaVulnerabilityTypeIdentifier<?>, Set<String>> getReferencedVulnerabilities() {
193-
return referencedVulnerabilities;
194-
}
195-
196-
public Map<AeaaAdvisoryTypeIdentifier<?>, Set<String>> getReferencedSecurityAdvisories() {
197-
return referencedSecurityAdvisories;
198-
}
199-
200-
public Map<AeaaOtherTypeIdentifier, Set<String>> getReferencedOtherIds() {
201-
return referencedOtherIds;
202-
}
203-
// START: MANAGE REFERENCED SECURITY ADVISORIES
266+
// START: MANAGE REFERENCED SECURITY ADVISORIES
204267

205268
public void addReferencedSecurityAdvisory(AeaaAdvisoryTypeIdentifier<?> source, String id) {
206269
if (source == null || id == null) {
@@ -339,6 +402,36 @@ public void removeOtherReferencedId(AeaaOtherTypeIdentifier source, String id) {
339402

340403
// END: MANAGE OTHER REFERENCED
341404

405+
public Map<AeaaVulnerabilityTypeIdentifier<?>, Set<String>> getReferencedVulnerabilities() {
406+
return referencedVulnerabilities;
407+
}
408+
409+
public Map<AeaaAdvisoryTypeIdentifier<?>, Set<String>> getReferencedSecurityAdvisories() {
410+
return referencedSecurityAdvisories;
411+
}
412+
413+
public Map<AeaaOtherTypeIdentifier, Set<String>> getReferencedOtherIds() {
414+
return referencedOtherIds;
415+
}
416+
417+
public Set<String> getReferencedSecurityAdvisories(AeaaAdvisoryTypeIdentifier<?> source) {
418+
synchronized (this.referencedSecurityAdvisories) {
419+
return this.referencedSecurityAdvisories.getOrDefault(source, Collections.emptySet());
420+
}
421+
}
422+
423+
public Set<String> getReferencedVulnerabilities(AeaaVulnerabilityTypeIdentifier<?> source) {
424+
synchronized (this.referencedVulnerabilities) {
425+
return this.referencedVulnerabilities.getOrDefault(source, Collections.emptySet());
426+
}
427+
}
428+
429+
public Set<String> getReferencedOtherIds(AeaaOtherTypeIdentifier source) {
430+
synchronized (this.referencedOtherIds) {
431+
return this.referencedOtherIds.getOrDefault(source, Collections.emptySet());
432+
}
433+
}
434+
342435
/* DATA TYPE CONVERSION METHODS */
343436

344437
@Override
@@ -392,6 +485,26 @@ public void appendFromBaseModel(AMB amb) {
392485
.distinct()
393486
.forEach(this::addDataSourceFromSourceString);
394487
}
488+
489+
if (StringUtils.hasText(amb.get(VulnerabilityMetaData.Attribute.WEAKNESS_DATA))) {
490+
for (AeaaCweEntry entry : AeaaCweEntry.fromJson(new JSONArray(amb.get(VulnerabilityMetaData.Attribute.WEAKNESS_DATA)))) {
491+
this.addWeakness(entry);
492+
}
493+
} else if (StringUtils.hasText(amb.get(VulnerabilityMetaData.Attribute.WEAKNESS))) {
494+
this.addWeakness(Arrays.asList(amb.get(VulnerabilityMetaData.Attribute.WEAKNESS).split(", ?")));
495+
}
496+
for (String id : this.getReferencedOtherIds(AeaaOtherTypeStore.CWE)) {
497+
this.addWeakness(id);
498+
}
499+
500+
if (StringUtils.hasText(amb.get(VulnerabilityMetaData.Attribute.CAPEC_DATA))) {
501+
for (AeaaCapecEntry entry : AeaaCapecEntry.fromJson(new JSONArray(amb.get(VulnerabilityMetaData.Attribute.CAPEC_DATA)))) {
502+
this.addAttackPattern(entry);
503+
}
504+
}
505+
for (String id : this.getReferencedOtherIds(AeaaOtherTypeStore.CAPEC)) {
506+
this.addAttackPattern(id);
507+
}
395508
}
396509

397510
@Override
@@ -410,6 +523,23 @@ public void appendToBaseModel(AMB modelBase) {
410523
modelBase.set(AdvisoryMetaData.Attribute.REFERENCED_SECURITY_ADVISORIES.getKey(), null);
411524
}
412525

526+
if (!this.weaknesses.isEmpty()) {
527+
modelBase.set(VulnerabilityMetaData.Attribute.WEAKNESS, String.join(", ", this.getWeaknessIds()));
528+
} else {
529+
modelBase.set(VulnerabilityMetaData.Attribute.WEAKNESS, null);
530+
}
531+
if (!this.weaknesses.isEmpty()) {
532+
modelBase.set(VulnerabilityMetaData.Attribute.WEAKNESS_DATA, new JSONArray(this.weaknesses.stream().map(AeaaCweEntry::toJson).collect(Collectors.toList())).toString());
533+
} else {
534+
modelBase.set(VulnerabilityMetaData.Attribute.WEAKNESS_DATA, null);
535+
}
536+
537+
if (!this.attackPatterns.isEmpty()) {
538+
modelBase.set(VulnerabilityMetaData.Attribute.CAPEC_DATA, new JSONArray(this.attackPatterns.stream().map(AeaaCapecEntry::toJson).collect(Collectors.toList())).toString());
539+
} else {
540+
modelBase.set(VulnerabilityMetaData.Attribute.CAPEC_DATA, null);
541+
}
542+
413543
if (!this.referencedOtherIds.isEmpty()) {
414544
modelBase.set(AdvisoryMetaData.Attribute.REFERENCED_OTHER.getKey(), AeaaContentIdentifierStore.toJson(this.referencedOtherIds).toString());
415545
} else {
@@ -468,6 +598,8 @@ public void appendFromDataClass(DC dataClass) {
468598

469599
this.addReferencedVulnerabilities(dataClass.getReferencedVulnerabilities());
470600
this.addReferencedSecurityAdvisories(dataClass.getReferencedSecurityAdvisories());
601+
dataClass.getWeaknesses().forEach(this::addWeakness);
602+
dataClass.getAttackPatterns().forEach(this::addAttackPattern);
471603
this.addOtherReferencedIds(dataClass.getReferencedOtherIds());
472604

473605
this.matchingSources.addAll(dataClass.getMatchingSources());
@@ -486,6 +618,22 @@ public void appendFromMap(Map<String, Object> input) {
486618
this.addReferencedSecurityAdvisories(AeaaAdvisoryTypeStore.get().fromListMultipleReferencedIds((List<Map<String, Object>>) input.get("referencedSecurityAdvisories")));
487619
}
488620

621+
for (String weakness : (Collection<String>) input.getOrDefault("cwe", Collections.EMPTY_SET)) {
622+
this.addWeakness(weakness);
623+
}
624+
625+
if (input.containsKey("cweData") && input.get("cweData") instanceof List) {
626+
for (AeaaCweEntry entry : AeaaCweEntry.fromJson(new JSONArray((List) input.get("cweData")))) {
627+
this.addWeakness(entry);
628+
}
629+
}
630+
631+
if (input.get("capecData") != null && input.get("capecData") instanceof List) {
632+
for (AeaaCapecEntry entry : AeaaCapecEntry.fromJson(new JSONArray((List) input.get("capecData")))) {
633+
this.addAttackPattern(entry);
634+
}
635+
}
636+
489637
if (input.containsKey("referencedOtherIds") && input.get("referencedOtherIds") instanceof List) {
490638
this.addOtherReferencedIds(AeaaOtherTypeStore.get().fromListMultipleReferencedIds((List<Map<String, Object>>) input.get("referencedOtherIds")));
491639
}
@@ -525,6 +673,10 @@ public void appendToJson(JSONObject json) {
525673
if (!this.referencedSecurityAdvisories.isEmpty()) {
526674
json.put("referencedSecurityAdvisories", AeaaContentIdentifierStore.toJson(this.referencedSecurityAdvisories));
527675
}
676+
677+
json.put("cweData", new JSONArray(this.weaknesses.stream().map(AeaaCweEntry::toJson).collect(Collectors.toList())));
678+
json.put("capecData", new JSONArray(this.attackPatterns.stream().map(AeaaCapecEntry::toJson).collect(Collectors.toList())));
679+
528680
if (!this.referencedOtherIds.isEmpty()) {
529681
json.put("referencedOtherIds", AeaaContentIdentifierStore.toJson(this.referencedOtherIds));
530682
}

0 commit comments

Comments
 (0)