Skip to content

Commit 5684643

Browse files
TristanCacquerayblackheaven
authored andcommitted
Add CVSS 3.0
1 parent 46e3a7f commit 5684643

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

code/cvss/src/Security/CVSS.hs

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import GHC.Float (powerFloat)
3838
data CVSSVersion
3939
= -- | Version 3.1: https://www.first.org/cvss/v3-1/
4040
CVSS31
41+
| -- | Version 3.0: https://www.first.org/cvss/v3.0/
42+
CVSS30
4143
| -- | Version 2.0: https://www.first.org/cvss/v2/
4244
CVSS20
4345

@@ -105,6 +107,7 @@ data Metric = Metric
105107
parseCVSS :: Text -> Either CVSSError CVSS
106108
parseCVSS txt
107109
| "CVSS:3.1/" `Text.isPrefixOf` txt = CVSS CVSS31 <$> validateComponents validateCvss31
110+
| "CVSS:3.0/" `Text.isPrefixOf` txt = CVSS CVSS30 <$> validateComponents validateCvss30
108111
| "CVSS:2.0/" `Text.isPrefixOf` txt = CVSS CVSS20 <$> validateComponents validateCvss20
109112
| otherwise = Left UnknownVersion
110113
where
@@ -124,6 +127,7 @@ parseCVSS txt
124127
cvssScore :: CVSS -> (Rating, Float)
125128
cvssScore cvss = case cvssVersion cvss of
126129
CVSS31 -> cvss31score (cvssMetrics cvss)
130+
CVSS30 -> cvss30score (cvssMetrics cvss)
127131
CVSS20 -> cvss20score (cvssMetrics cvss)
128132

129133
-- | Explain the CVSS metrics.
@@ -140,9 +144,11 @@ cvssVectorStringOrdered = cvssShow True
140144

141145
cvssShow :: Bool -> CVSS -> Text
142146
cvssShow ordered cvss = case cvssVersion cvss of
143-
CVSS31 -> Text.intercalate "/" ("CVSS:3.1" : map toComponent (cvssOrder (cvssMetrics cvss)))
144-
CVSS20 -> Text.intercalate "/" ("CVSS:2.0" : map toComponent (cvssOrder (cvssMetrics cvss)))
147+
CVSS31 -> Text.intercalate "/" ("CVSS:3.1" : components)
148+
CVSS30 -> Text.intercalate "/" ("CVSS:3.0" : components)
149+
CVSS20 -> Text.intercalate "/" ("CVSS:2.0" : components)
145150
where
151+
components = map toComponent (cvssOrder (cvssMetrics cvss))
146152
toComponent :: Metric -> Text
147153
toComponent (Metric (MetricShortName name) (MetricValueChar value)) = Text.snoc (name <> ":") value
148154
cvssOrder metrics
@@ -156,6 +162,7 @@ newtype CVSSDB = CVSSDB [MetricGroup]
156162
cvssDB :: CVSSVersion -> CVSSDB
157163
cvssDB v = case v of
158164
CVSS31 -> cvss31
165+
CVSS30 -> cvss30
159166
CVSS20 -> cvss20
160167

161168
-- | Description of a metric group.
@@ -332,6 +339,102 @@ validateCvss31 metrics = do
332339
traverse_ (\t -> t metrics) [validateUnique, validateKnown cvss31, validateRequired cvss31]
333340
pure metrics
334341

342+
cvss30 :: CVSSDB
343+
cvss30 =
344+
CVSSDB
345+
[ MetricGroup "Base" baseMetrics
346+
]
347+
where
348+
baseMetrics =
349+
[ MetricInfo
350+
"Attack Vector"
351+
"AV"
352+
True
353+
[ MetricValue "Network" (C 'N') 0.85 Nothing "A vulnerability exploitable with network access means the vulnerable component is bound to the network stack and the attacker's path is through OSI layer 3 (the network layer)."
354+
, MetricValue "Adjacent" (C 'A') 0.62 Nothing "A vulnerability exploitable with adjacent network access means the vulnerable component is bound to the network stack"
355+
, MetricValue "Local" (C 'L') 0.55 Nothing "A vulnerability exploitable with Local access means that the vulnerable component is not bound to the network stack, and the attacker's path is via read/write/execute capabilities."
356+
, MetricValue "Physical" (C 'P') 0.2 Nothing "A vulnerability exploitable with Physical access requires the attacker to physically touch or manipulate the vulnerable component."
357+
]
358+
, MetricInfo
359+
"Attack Complexity"
360+
"AC"
361+
True
362+
[ MetricValue "Low" (C 'L') 0.77 Nothing "Specialized access conditions or extenuating circumstances do not exist."
363+
, MetricValue "High" (C 'H') 0.44 Nothing "A successful attack depends on conditions beyond the attacker's control."
364+
]
365+
, MetricInfo
366+
"Privileges Required"
367+
"PR"
368+
True
369+
[ MetricValue "None" (C 'N') 0.85 Nothing "The attacker is unauthorized prior to attack, and therefore does not require any access to settings or files to carry out an attack."
370+
, MetricValue "Low" (C 'L') 0.62 (Just 0.68) "The attacker is authorized with (i.e. requires) privileges that provide basic user capabilities that could normally affect only settings and files owned by a user."
371+
, MetricValue "High" (C 'H') 0.27 (Just 0.5) "The attacker is authorized with (i.e. requires) privileges that provide significant (e.g. administrative) control over the vulnerable component that could affect component-wide settings and files."
372+
]
373+
, MetricInfo
374+
"User Interaction"
375+
"UI"
376+
True
377+
[ MetricValue "None" (C 'N') 0.85 Nothing "The vulnerable system can be exploited without interaction from any user."
378+
, MetricValue "Required" (C 'R') 0.62 Nothing "Successful exploitation of this vulnerability requires a user to take some action before the vulnerability can be exploited."
379+
]
380+
, MetricInfo
381+
"Scope"
382+
"S"
383+
True
384+
[ MetricValue "Unchanged" (C 'U') Unchanged Nothing "An exploited vulnerability can only affect resources managed by the same authority."
385+
, MetricValue "Changed" (C 'C') Changed Nothing "An exploited vulnerability can affect resources beyond the authorization privileges intended by the vulnerable component."
386+
]
387+
, MetricInfo
388+
"Confidentiality Impact"
389+
"C"
390+
True
391+
[ mkHigh "There is a total loss of confidentiality, resulting in all resources within the impacted component being divulged to the attacker."
392+
, mkLow "There is some loss of confidentiality."
393+
, mkNone "There is no loss of confidentiality within the impacted component."
394+
]
395+
, MetricInfo
396+
"Integrity Impact"
397+
"I"
398+
True
399+
[ mkHigh "There is a total loss of integrity, or a complete loss of protection."
400+
, mkLow "Modification of data is possible, but the attacker does not have control over the consequence of a modification, or the amount of modification is limited."
401+
, mkNone "There is no loss of integrity within the impacted component."
402+
]
403+
, MetricInfo
404+
"Availability Impact"
405+
"A"
406+
True
407+
[ mkHigh "There is a total loss of availability, resulting in the attacker being able to fully deny access to resources in the impacted component"
408+
, mkLow "Performance is reduced or there are interruptions in resource availability."
409+
, mkNone "There is no impact to availability within the impacted component."
410+
]
411+
]
412+
mkHigh = MetricValue "High" (C 'H') 0.56 Nothing
413+
mkLow = MetricValue "Low" (C 'L') 0.22 Nothing
414+
mkNone = MetricValue "None" (C 'N') 0 Nothing
415+
416+
-- | Implementation of Section 8.1 "Base"
417+
cvss30score :: [Metric] -> (Rating, Float)
418+
cvss30score metrics = (toRating score, score)
419+
where
420+
score
421+
| impact <= 0 = 0
422+
| scope == Unchanged = roundup (min (impact + exploitability) 10)
423+
| otherwise = roundup (min (1.08 * (impact + exploitability)) 10)
424+
impact
425+
| scope == Unchanged = scope * iscBase
426+
| otherwise = scope * (iscBase - 0.029) - 3.25 * (powerFloat (iscBase - 0.02) 15)
427+
iscBase = 1 - (1 - gm "Confidentiality Impact") * (1 - gm "Integrity Impact") * (1 - gm "Availability Impact")
428+
scope = gm "Scope"
429+
430+
exploitability = 8.22 * gm "Attack Vector" * gm "Attack Complexity" * gm "Privileges Required" * gm "User Interaction"
431+
gm = getMetricValue cvss30 metrics scope
432+
433+
validateCvss30 :: [Metric] -> Either CVSSError [Metric]
434+
validateCvss30 metrics = do
435+
traverse_ (\t -> t metrics) [validateUnique, validateKnown cvss30, validateRequired cvss30]
436+
pure metrics
437+
335438
cvss20 :: CVSSDB
336439
cvss20 =
337440
CVSSDB

code/cvss/test/Spec.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ examples =
2424
[ ("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N", 5.8, CVSS.Medium)
2525
, ("CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N", 6.4, CVSS.Medium)
2626
, ("CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N", 3.1, CVSS.Low)
27+
, ("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", 6.1, CVSS.Medium)
28+
, ("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N", 6.4, CVSS.Medium)
29+
, ("CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N", 3.1, CVSS.Low)
30+
, ("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H", 9.9, CVSS.Critical)
31+
, ("CVSS:3.0/AV:L/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:L", 4.2, CVSS.Medium)
2732
, ("CVSS:2.0/AV:N/AC:L/Au:N/C:N/I:N/A:C", 7.8, CVSS.High)
2833
, ("CVSS:2.0/AV:N/AC:L/Au:N/C:C/I:C/A:C", 10, CVSS.Critical)
2934
, ("CVSS:2.0/AV:L/AC:H/Au:N/C:C/I:C/A:C", 6.2, CVSS.Medium)

0 commit comments

Comments
 (0)