-
Notifications
You must be signed in to change notification settings - Fork 33
/
vulnerability.cljc
410 lines (354 loc) · 16.5 KB
/
vulnerability.cljc
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
(ns ctim.schemas.vulnerability
(:require #?(:clj [flanders.core :as f :refer [def-entity-type
def-enum-type
def-map-type def-eq]]
:cljs [flanders.core :as f :refer-macros [def-entity-type
def-enum-type
def-map-type def-eq]])
#?(:clj [ctim.lib.generators :as gen])
[clojure.spec.alpha :as spec]
[ctim.lib.predicates :as pred]
[ctim.schemas.common :as c]
[ctim.schemas.vocabularies :as v]))
(def type-identifier "vulnerability")
(def-eq VulnerabilityTypeIdentifier type-identifier
:description "The fixed value \"vulnerability\"")
(def vulnerability-desc
(str "a mistake in software that can be directly "
"used by a hacker to gain access to a system or network"))
(def vulnerability-desc-link
"[Vulnerability](http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714334)")
(defn valid-score?
"check that a score is no less than 0 and no greater than 10"
[score]
(<= 0 score 10))
(def Score
(f/num
:description "a Score number from 0 to 10"
:spec valid-score?
:float? true
#?(:clj :gen)
#?(:clj gen/score)))
(def cvss-v3-vector-string-exp
#"^CVSS:3\.[0-1]/((AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$")
(comment
;; base, temporal, environmental vectors
;; for use in building the regexp expressions in the vulnerability
:reference "https://www.first.org/cvss/v2/guide#2-4-Base-Temporal-Environmental-Vectors"
"Base AV:[L,A,N]/AC:[H,M,L]/Au:[M,S,N]/C:[N,P,C]/I:[N,P,C]/A:[N,P,C]
Temporal E:[U,POC,F,H,ND]/RL:[OF,TF,W,U,ND]/RC:[UC,UR,C,ND]
Environmental CDP:[N,L,LM,MH,H,ND]/TD:[N,L,M,H,ND]/CR:[L,M,H,ND]/IR:[L,M,H,ND]/AR:[L,M,H,ND]")
;; example: "AV:N/AC:M/Au:N/C:C/I:C/A:C"
(def cvss-v2-vector-string-exp
#"^AV:[LAN]/AC:[HML]/Au:[NSM]/C:[NPC]/I:[NPC]/A:[NPC]$")
;; example: "E:U/RL:OF/RC:C"
(def cvss-v2-temporal-vector-string-exp
#"^E:(U|POC|F|H|ND)/RL:(OF|TF|W|U|ND)/RC:(UC|UR|C|ND)$")
;; example: "CDP:N/TD:L/CR:L/IR:ND/AR:ND"
(def cvss-v2-environmental-vector-string-exp
#"^CDP:(N|L|LM|MH|H|ND)/TD:(N|L|M|H|ND)/CR:(L|M|H|ND)/IR:(L|M|H|ND)/AR:(L|M|H|ND)$")
(defn cvss-v2-vector-string?
"validate a v2 vector string using a regexp"
[s]
(re-matches cvss-v2-vector-string-exp s))
(defn cvss-v2-temporal-vector-string?
"validate a v2 temporal vector string using a regexp"
[s]
(re-matches cvss-v2-temporal-vector-string-exp s))
(defn cvss-v2-environmental-vector-string?
"validate a v2 environmental vector string using a regexp"
[s]
(re-matches cvss-v2-environmental-vector-string-exp s))
(defn cvss-v3-vector-string?
"validate a v3 vector string using a regexp"
[s]
(re-matches cvss-v3-vector-string-exp s))
(def CVSSv2VectorString
(f/str
:description
(str "a text representation of a set of CVSSv2 metrics. "
"It is commonly used to record or transfer "
"CVSSv2 metric information in a concise form")
:spec cvss-v2-vector-string?
#?(:clj :gen)
#?(:clj gen/cvss-v2-vector-string)))
(def CVSSv2TemporalVectorString
(f/str
:description
(str "A text representation of a set of CVSSv2 temporal metrics. "
"Temporal metrics allow analysists to calculate threat severity "
"based on temporal factors such as reliability of vulnerability "
"reports, availability of mitigations, and the ease or difficulty "
"of conducting the exploit. "
"It is commonly used to record or transfer "
"CVSSv2 metric information in a concise form")
:spec cvss-v2-temporal-vector-string?
#?(:clj :gen)
#?(:clj gen/cvss-v2-temporal-vector-string)))
(def CVSSv2EnvironmentalVectorString
(f/str
:description
(str "A text representation of a set of CVSSv2 environmental metrics. "
"Environmental metrics allow analysists to calculate threat "
"scores in relation to environmental security requirements, "
"collateral damage potential, and target availability. "
"It is commonly used to record or transfer "
"CVSSv2 metric information in a concise form")
:spec cvss-v2-environmental-vector-string?
#?(:clj :gen)
#?(:clj gen/cvss-v2-environmental-vector-string)))
(def CVSSv3VectorString
(f/str
:description
(str "a text representation of a set of CVSSv3 metrics. "
"It is commonly used to record or transfer "
"CVSSv3 metric information in a concise form")
:spec cvss-v3-vector-string?
#?(:clj :gen)
#?(:clj gen/cvss-v3-vector-string)))
(def-map-type CVSSv2
(concat
(f/required-entries
(f/entry :vector_string CVSSv2VectorString)
(f/entry :base_score Score)
(f/entry :base_severity v/HighMedLow))
(f/optional-entries
(f/entry :impact_score Score)
(f/entry :exploitability_score Score)
(f/entry :access_vector v/CVSSv2AccessVector)
(f/entry :access_complexity v/CVSSv2AccessComplexity)
(f/entry :authentication v/CVSSv2Authentication)
(f/entry :confidentiality_impact v/CVSSv2ConfidentialityImpact)
(f/entry :integrity_impact v/CVSSv2IntegrityImpact)
(f/entry :availability_impact v/CVSSv2AvailabilityImpact)
;; CVSS v2.0 Temporal Factors
(f/entry :exploitability v/CVSSv2Exploitability)
(f/entry :remediation_level v/CVSSv2RemediationLevel)
(f/entry :report_confidence v/CVSSv2ReportConfidence)
(f/entry :temporal_vector_string CVSSv2TemporalVectorString)
;; CVSS v2.0 Environmental Factors
(f/entry :collateral_damage_potential v/CVSSv2CollateralDamagePotential)
(f/entry :target_distribution v/CVSSv2TargetDistribution)
(f/entry :confidentiality_requirement v/CVSSv2SecurityRequirement)
(f/entry :integrity_requirement v/CVSSv2SecurityRequirement)
(f/entry :availability_requirement v/CVSSv2SecurityRequirement)
(f/entry :environmental_vector_string CVSSv2EnvironmentalVectorString)
;; CVSS v2.0 metadata flags added in NVD 0.1_beta - 2017-07-05
(f/entry :obtain_all_privilege f/any-bool)
(f/entry :obtain_user_privilege f/any-bool)
(f/entry :obtain_other_privilege f/any-bool)
(f/entry :user_interaction_required f/any-bool))))
(def-map-type CVSSv3
(concat
(f/required-entries
(f/entry :vector_string CVSSv3VectorString)
(f/entry :base_score Score)
(f/entry :base_severity v/CVSSv3Severity))
(f/optional-entries
(f/entry :impact_score Score)
(f/entry :exploitability_score Score)
(f/entry :attack_vector v/CVSSv3AttackVector
:description (str "Reflects the context by which "
"vulnerability exploitation is possible"))
(f/entry :modified_attack_vector v/CVSSv3ModifiedAttackVector
:description "modified attack vector")
(f/entry :attack_complexity v/CVSSv3AttackComplexity
:description (str "describes the conditions beyond the attacker's "
"control that must exist in order to exploit the "
"vulnerability"))
(f/entry :modified_attack_complexity v/CVSSv3ModifiedAttackComplexity
:description "modified attack complexity")
(f/entry :privileges_required v/CVSSv3PrivilegesRequired
:description (str "describes the level of privileges an attacker "
"must possess before successfully exploiting the vulnerability"))
(f/entry :modified_privileges_required v/CVSSv3ModifiedPrivilegesRequired
:description "modified privileges required")
(f/entry :user_interaction v/CVSSv3UserInteraction
:description (str "captures the requirement for a user, "
"other than the attacker, to participate in "
"the successful compromise of the vulnerable component"))
(f/entry :modified_user_interaction v/CVSSv3ModifiedUserInteraction
:description "modified user interaction")
(f/entry :scope v/CVSSv3Scope
:description (str "the ability for a vulnerability in one "
"software component to impact resources beyond "
"its means, or privileges"))
(f/entry :modified_scope v/CVSSv3ModifiedScope
:description "modified scope")
(f/entry :confidentiality_impact v/CVSSv3ConfidentialityImpact
:description (str "measures the impact to the confidentiality of "
"the information resources managed by a software "
"component due to a successfully exploited vulnerability"))
(f/entry :modified_confidentiality_impact v/CVSSv3ModifiedConfidentialityImpact
:description "modified confidentiality impact")
(f/entry :integrity_impact v/CVSSv3IntegrityImpact
:description (str "measures the impact to integrity "
"of a successfully exploited vulnerability"))
(f/entry :modified_integrity_impact v/CVSSv3ModifiedIntegrityImpact
:description (str "modified integrity impact"))
(f/entry :availability_impact v/CVSSv3AvailabilityImpact
:description (str "measures the impact to the availability "
"of the impacted component resulting from a successfully "
"exploited vulnerability"))
(f/entry :modified_availability_impact v/CVSSv3ModifiedAvailabilityImpact
:description "modified availability impact")
(f/entry :exploit_code_maturity v/CVSSv3ExploitCodeMaturity
:description "measures the likelihood of the vulnerability being attacked")
(f/entry :remediation_level v/CVSSv3RemediationLevel
:description (str "Remediation Level of a vulnerability "
"is an important factor for prioritization"))
(f/entry :report_confidence v/CVSSv3ReportConfidence
:description (str "measures the degree of confidence in the existence "
"of the vulnerability and the credibility of the "
"known technical details"))
(f/entry :temporal_score Score
:description (str "Round up(CVSSv3BaseScore × "
"CVSSv3ExploitCodeMaturity × "
"CVSSv3RemediationLevel × "
"CVSSv3ReportConfidence)"))
(f/entry :temporal_severity v/CVSSv3Severity
:description "temporal severity")
;; requirements
(f/entry :availability_requirement v/CVSSv3SecurityRequirements)
(f/entry :confidentiality_requirement v/CVSSv3SecurityRequirements)
(f/entry :integrity_requirement v/CVSSv3SecurityRequirements)
;; optional scores
(f/entry :environmental_score Score)
(f/entry :environmental_severity v/CVSSv3Severity))))
(def-map-type VulnerabilityImpact
(f/optional-entries
(f/entry :cvss_v2 CVSSv2)
(f/entry :cvss_v3 CVSSv3)))
;; CVE Metadata (ID Assigner), description, references, v3 impact data published_date, lastmodified_date
(def-map-type CVEDataMeta
(f/optional-entries
(f/entry :id c/ShortString)
(f/entry :assigner c/ShortString)))
(def-map-type CVE
(f/required-entries
(f/entry :cve_data_meta CVEDataMeta)))
(defn formatted-cpe-23-string-regex
"Translated from NIST 7695 CPE 2.3 formatted string ABNF, at
https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7695.pdf"
[]
(let [spec1 "\\?"
spec2 "\\*"
spec_chrs (format "(?:%s+|%s)" spec1 spec2)
unreserved "[a-z0-9\\-\\.\\_]"
escape "\\\\"
special (format "[%s%s]" spec1 spec2)
punc (format "[%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s]"
"!" "\"" "#" "\\$" "%" "&" "'" "\\(" "\\)" "\\+" ","
"/" ":" ";" "<" "=" ">" "@" "\\[" "\\]" "\\^" "`" "\\{"
"\\|" "\\}" "~")
quoted (format "%s(?:%s|%s|%s)" escape escape special punc)
logical "[\\*\\-]"
avstring (format "(?:(?:%s?(?:%s|%s)+%s?)|%s)" spec_chrs unreserved quoted spec_chrs logical)
part (format "(?:%s|%s)" "[hoa]" logical)
vendor avstring
product avstring
version avstring
version_update avstring
edition avstring
language "[a-z]{2,3}"
region "(?:[a-z]{2}|[0-9]{3})"
langtag (format "%s(?:-%s)?" language region)
lang (format "(?:%s|%s)" langtag logical)
sw_edition avstring
target_sw avstring
target_hw avstring
other avstring
component-list (format "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s"
part vendor product version version_update
edition lang sw_edition target_sw
target_hw other)]
(re-pattern (format "(?i)cpe:2\\.3:%s" component-list))))
(defn formatted-cpe-23-string?
"Returns `s` when it is a formatted CPE 2.3 string, otherwise returns nil."
[s]
(re-matches (formatted-cpe-23-string-regex) s))
(def FormattedCPE23String
(f/str
:description "A text representation of a software or hardware platform."
:spec formatted-cpe-23-string?
#?(:clj :gen)
#?(:clj gen/formatted-cpe-23-string)))
(def cpe-node-operators
#{"OR" "AND"})
(def-enum-type cpe-node-operator-string
cpe-node-operators
:description (str "The operator string influences how seqs of cpe matches "
"are related to one another.")
:gen (spec/gen cpe-node-operators))
(def Version
(f/str
:description "A string representing a bound of a version in the CPE."
:spec (spec/and string? (pred/max-len 64))
#?(:clj :gen)
#?(:clj gen/semver)))
(def-map-type CPEMatch
(concat
(f/required-entries
(f/entry :vulnerable f/any-bool)
(f/entry :cpe23Uri FormattedCPE23String))
(f/optional-entries
(f/entry :versionStartIncluding Version
:description (str "A string representing the lower bound(inclusive) of version "
"in the CPE."))
(f/entry :versionEndIncluding Version
:description (str "A string representing the upper bound(inclusive) of version "
"in the CPE."))
(f/entry :versionStartExcluding Version
:description (str "A string representing the lower bound(exclusive) of version "
"in the CPE."))
(f/entry :versionEndExcluding Version
:description (str "A string representing the upper bound(exclusive) of version "
"in the CPE.")))))
(def-map-type CPELeafNode
(concat
(f/required-entries
(f/entry :operator cpe-node-operator-string)
(f/entry :cpe_match (f/seq-of CPEMatch)))
(f/optional-entries
(f/entry :negate f/any-bool
:description "Negates operator when true."))))
(def-map-type CPENode
(concat
(f/required-entries
(f/entry :operator cpe-node-operator-string))
(f/optional-entries
(f/entry :cpe_match (f/seq-of CPEMatch))
(f/entry :children (f/seq-of CPELeafNode))
(f/entry :negate f/any-bool
:description "Negates operator when true."))))
(def-map-type Configurations
(f/required-entries
(f/entry :CVE_data_version c/ShortString)
(f/entry :nodes (f/seq-of CPENode))))
(def-entity-type Vulnerability
{:description vulnerability-desc
:reference vulnerability-desc-link}
c/base-entity-entries
c/describable-entity-entries
c/sourcable-object-entries
(f/required-entries
(f/entry :description c/Markdown
:description
(str "A description that provides more details and context about the Vulnerability, "
"potentially including its purpose and its key characteristics."))
(f/entry :type VulnerabilityTypeIdentifier
:description (str "The fixed value " type-identifier)))
(f/optional-entries
(f/entry :cve CVE)
(f/entry :impact VulnerabilityImpact)
(f/entry :configurations Configurations)
(f/entry :published_date c/Time)
(f/entry :last_modified_date c/Time)))
(def-entity-type NewVulnerability
"For submitting a new vulnerability"
(:entries Vulnerability)
c/base-new-entity-entries
(f/optional-entries
(f/entry :type VulnerabilityTypeIdentifier)))
(def VulnerabilityRef
(c/ref-for-type type-identifier))