1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.reporting;
19
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import org.owasp.dependencycheck.dependency.Dependency;
25 import org.owasp.dependencycheck.dependency.Vulnerability;
26 import org.owasp.dependencycheck.dependency.naming.CpeIdentifier;
27 import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
28 import org.owasp.dependencycheck.dependency.naming.Identifier;
29 import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
30 import org.owasp.dependencycheck.utils.SeverityUtil;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import us.springett.parsers.cpe.Cpe;
34 import us.springett.parsers.cpe.exceptions.CpeEncodingException;
35 import us.springett.parsers.cpe.util.Convert;
36
37
38
39
40
41
42 public class ReportTool {
43
44
45
46
47 private static final Logger LOGGER = LoggerFactory.getLogger(ReportTool.class);
48
49
50
51
52
53
54
55
56 public String identifierToSuppressionId(Identifier id) {
57 if (id instanceof PurlIdentifier) {
58 final PurlIdentifier purl = (PurlIdentifier) id;
59 return purl.toString();
60 } else if (id instanceof CpeIdentifier) {
61 try {
62 final CpeIdentifier cpeId = (CpeIdentifier) id;
63 final Cpe cpe = cpeId.getCpe();
64 return String.format("cpe:/%s:%s:%s", Convert.wellFormedToCpeUri(cpe.getPart()),
65 Convert.wellFormedToCpeUri(cpe.getWellFormedVendor()),
66 Convert.wellFormedToCpeUri(cpe.getWellFormedProduct()));
67 } catch (CpeEncodingException ex) {
68 LOGGER.debug("Unable to convert to cpe URI", ex);
69 }
70 } else if (id instanceof GenericIdentifier) {
71 return id.getValue();
72 }
73 return null;
74 }
75
76
77
78
79
80
81
82 public Double estimateSeverity(String severity) {
83 return SeverityUtil.estimateCvssV2(severity);
84 }
85
86
87
88
89
90
91
92 public Collection<SarifRule> convertToSarifRules(List<Dependency> dependencies) {
93 final Map<String, SarifRule> rules = new HashMap<>();
94 for (Dependency d : dependencies) {
95 for (Vulnerability v : d.getVulnerabilities()) {
96 if (!rules.containsKey(v.getName())) {
97 final SarifRule r = new SarifRule(v.getName(),
98 buildShortDescription(d, v, v.getKnownExploitedVulnerability() != null),
99 buildDescription(v.getDescription(), v.getKnownExploitedVulnerability()),
100 v.getSource().name(),
101 v.getCvssV2(),
102 v.getCvssV3(),
103 v.getCvssV4());
104 rules.put(v.getName(), r);
105 }
106 }
107 }
108 return rules.values();
109 }
110
111 private String determineScore(Vulnerability vuln) {
112 if (vuln.getUnscoredSeverity() != null) {
113 if ("0.0".equals(vuln.getUnscoredSeverity())) {
114 return "unknown";
115 } else {
116 return normalizeSeverity(vuln.getUnscoredSeverity().toLowerCase());
117 }
118 } else if (vuln.getCvssV4() != null && vuln.getCvssV4().getCvssData().getBaseSeverity() != null) {
119 return normalizeSeverity(vuln.getCvssV4().getCvssData().getBaseSeverity().value().toLowerCase());
120 } else if (vuln.getCvssV3() != null && vuln.getCvssV3().getCvssData().getBaseSeverity() != null) {
121 return normalizeSeverity(vuln.getCvssV3().getCvssData().getBaseSeverity().value().toLowerCase());
122 } else if (vuln.getCvssV2() != null && vuln.getCvssV2().getCvssData().getBaseSeverity() != null) {
123 return normalizeSeverity(vuln.getCvssV2().getCvssData().getBaseSeverity());
124 }
125 return "unknown";
126 }
127
128
129
130
131
132
133 public String normalizeSeverity(String sev) {
134 switch (sev.toLowerCase()) {
135 case "critical":
136 return "critical";
137 case "high":
138 return "high";
139 case "medium":
140 case "moderate":
141 return "medium";
142 case "low":
143 case "informational":
144 case "info":
145 return "low";
146 default:
147 return "unknown";
148 }
149 }
150
151
152
153
154
155
156
157
158
159 private String buildShortDescription(Dependency d, Vulnerability vuln, boolean knownExploited) {
160 final StringBuilder sb = new StringBuilder();
161 sb.append(determineScore(vuln))
162 .append(" severity - ")
163 .append(vuln.getName());
164 if (vuln.getCwes() != null && !vuln.getCwes().isEmpty()) {
165 final String cwe = vuln.getCwes().getFullCwes().values().iterator().next();
166 if (cwe != null && !"NVD-CWE-Other".equals(cwe) && !"NVD-CWE-noinfo".equals(cwe)) {
167 sb.append(" ").append(cwe);
168 }
169 }
170 sb.append(" vulnerability in ");
171 if (d.getSoftwareIdentifiers() != null && !d.getSoftwareIdentifiers().isEmpty()) {
172 sb.append(d.getSoftwareIdentifiers().iterator().next());
173 } else {
174 sb.append(d.getDisplayFileName());
175 }
176 if (knownExploited) {
177 sb.append(" *Known Exploited Vulnerability*");
178 }
179 return sb.toString();
180 }
181
182 private String buildDescription(String description,
183 org.owasp.dependencycheck.data.knownexploited.json.Vulnerability knownExploitedVulnerability) {
184 final StringBuilder sb = new StringBuilder();
185 if (knownExploitedVulnerability != null) {
186 sb.append("CISA Known Exploited Vulnerability\n");
187 if (knownExploitedVulnerability.getVendorProject() != null) {
188 sb.append("Vendor/Project: ").append(knownExploitedVulnerability.getVendorProject()).append("\n");
189 }
190 if (knownExploitedVulnerability.getProduct() != null) {
191 sb.append("Product: ").append(knownExploitedVulnerability.getProduct()).append("\n");
192 }
193 if (knownExploitedVulnerability.getVulnerabilityName() != null) {
194 sb.append("Vulnerability Name: ").append(knownExploitedVulnerability.getVulnerabilityName()).append("\n");
195 }
196 if (knownExploitedVulnerability.getDateAdded() != null) {
197 sb.append("Date Added: ").append(knownExploitedVulnerability.getDateAdded()).append("\n");
198 }
199 if (knownExploitedVulnerability.getShortDescription() != null) {
200 sb.append("Short Description: ").append(knownExploitedVulnerability.getShortDescription()).append("\n");
201 }
202 if (knownExploitedVulnerability.getRequiredAction() != null) {
203 sb.append("Required Action: ").append(knownExploitedVulnerability.getRequiredAction()).append("\n");
204 }
205 if (knownExploitedVulnerability.getDueDate() != null) {
206 sb.append("Due Date").append(knownExploitedVulnerability.getDueDate()).append("\n");
207 }
208 if (knownExploitedVulnerability.getNotes() != null) {
209 sb.append("Notes: ").append(knownExploitedVulnerability.getNotes()).append("\n");
210 }
211 sb.append("\n");
212 }
213 sb.append(description);
214 return sb.toString();
215 }
216 }