1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.dependency;
19
20 import org.sonatype.ossindex.service.api.cvss.Cvss3Severity;
21
22 import java.io.Serializable;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.List;
26
27
28
29
30
31
32 public class CvssV3 implements Serializable {
33
34
35
36
37 private static final long serialVersionUID = -315810090425928920L;
38
39
40
41
42 private static final List<String> BASE_METRICS = Arrays.asList("AV", "AC", "PR", "UI", "S", "C", "I", "A");
43
44
45
46
47 private final String attackVector;
48
49
50
51 private final String attackComplexity;
52
53
54
55 private final String privilegesRequired;
56
57
58
59 private final String userInteraction;
60
61
62
63 private final String scope;
64
65
66
67 private final String confidentialityImpact;
68
69
70
71 private final String integrityImpact;
72
73
74
75 private final String availabilityImpact;
76
77
78
79 private final float baseScore;
80
81
82
83 private final String baseSeverity;
84
85
86
87 private final Float exploitabilityScore;
88
89
90
91 private final Float impactScore;
92
93
94
95 private final String version;
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public CvssV3(String attackVector, String attackComplexity, String privilegesRequired,
113 String userInteraction, String scope, String confidentialityImpact, String integrityImpact,
114 String availabilityImpact, float baseScore, String baseSeverity) {
115 this(attackVector, attackComplexity, privilegesRequired, userInteraction, scope, confidentialityImpact,
116 integrityImpact, availabilityImpact, baseScore, baseSeverity, null, null, null);
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public CvssV3(String attackVector, String attackComplexity, String privilegesRequired,
137 String userInteraction, String scope, String confidentialityImpact, String integrityImpact,
138 String availabilityImpact, float baseScore, String baseSeverity, Float exploitabilityScore, Float impactScore, String version) {
139 this.attackVector = attackVector;
140 this.attackComplexity = attackComplexity;
141 this.privilegesRequired = privilegesRequired;
142 this.userInteraction = userInteraction;
143 this.scope = scope;
144 this.confidentialityImpact = confidentialityImpact;
145 this.integrityImpact = integrityImpact;
146 this.availabilityImpact = availabilityImpact;
147 this.baseScore = baseScore;
148 this.baseSeverity = baseSeverity;
149 this.exploitabilityScore = exploitabilityScore;
150 this.impactScore = impactScore;
151 this.version = version;
152 }
153
154
155
156
157
158
159
160
161
162
163
164 public CvssV3(String vectorString, float baseScore) {
165 if (!vectorString.startsWith("CVSS:3")) {
166 throw new IllegalArgumentException("Not a valid CVSSv3 vector string: " + vectorString);
167 }
168 this.version = vectorString.substring(5, vectorString.indexOf('/'));
169 final String[] metricStrings = vectorString.substring(vectorString.indexOf('/') + 1).split("/");
170 final HashMap<String, String> metrics = new HashMap<>();
171 for (int i = 0; i < metricStrings.length; i++) {
172 final String[] metricKeyVal = metricStrings[i].split(":");
173 if (metricKeyVal.length != 2) {
174 throw new IllegalArgumentException(
175 String.format("Not a valid CVSSv3 vector string '%s', invalid metric component '%s'",
176 vectorString, metricStrings[i]));
177 }
178 metrics.put(metricKeyVal[0], metricKeyVal[1]);
179 }
180 if (!metrics.keySet().containsAll(BASE_METRICS)) {
181 throw new IllegalArgumentException(
182 String.format("Not a valid CVSSv3 vector string '%s'; missing one or more required Base Metrics;",
183 vectorString));
184 }
185 this.attackVector = metrics.get("AV");
186 this.attackComplexity = metrics.get("AC");
187 this.privilegesRequired = metrics.get("PR");
188 this.userInteraction = metrics.get("UI");
189 this.scope = metrics.get("S");
190 this.confidentialityImpact = metrics.get("C");
191 this.integrityImpact = metrics.get("I");
192 this.availabilityImpact = metrics.get("A");
193 this.baseScore = baseScore;
194 this.baseSeverity = Cvss3Severity.of(baseScore).name();
195 this.exploitabilityScore = null;
196 this.impactScore = null;
197 }
198
199
200
201
202
203
204 public String getAttackVector() {
205 return attackVector;
206 }
207
208
209
210
211
212
213 public String getAttackComplexity() {
214 return attackComplexity;
215 }
216
217
218
219
220
221
222 public String getPrivilegesRequired() {
223 return privilegesRequired;
224 }
225
226
227
228
229
230
231 public String getUserInteraction() {
232 return userInteraction;
233 }
234
235
236
237
238
239
240 public String getScope() {
241 return scope;
242 }
243
244
245
246
247
248
249 public String getConfidentialityImpact() {
250 return confidentialityImpact;
251 }
252
253
254
255
256
257
258 public String getIntegrityImpact() {
259 return integrityImpact;
260 }
261
262
263
264
265
266
267 public String getAvailabilityImpact() {
268 return availabilityImpact;
269 }
270
271
272
273
274
275
276 public float getBaseScore() {
277 return baseScore;
278 }
279
280
281
282
283
284
285 public String getBaseSeverity() {
286 return baseSeverity;
287 }
288
289
290
291
292
293
294 public String getVersion() {
295 return version;
296 }
297
298
299
300
301
302
303 public Float getexploitabilityScore() {
304 return exploitabilityScore;
305 }
306
307
308
309
310
311
312 public Float getimpactScore() {
313 return impactScore;
314 }
315
316 @Override
317 public String toString() {
318 return String.format("CVSS:%s/AV:%s/AC:%s/PR:%s/UI:%s/S:%s/C:%s/I:%s/A:%s",
319 version == null ? "" : version,
320 attackVector == null ? "" : attackVector.substring(0, 1),
321 attackComplexity == null ? "" : attackComplexity.substring(0, 1),
322 privilegesRequired == null ? "" : privilegesRequired.substring(0, 1),
323 userInteraction == null ? "" : userInteraction.substring(0, 1),
324 scope == null ? "" : scope.substring(0, 1),
325 confidentialityImpact == null ? "" : confidentialityImpact.substring(0, 1),
326 integrityImpact == null ? "" : integrityImpact.substring(0, 1),
327 availabilityImpact == null ? "" : availabilityImpact.substring(0, 1));
328 }
329
330 }