cvss_rating 0.2.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +32 -3
- data/cvss_rating.gemspec +1 -1
- data/lib/cvss3_rating.rb +106 -0
- data/lib/cvss_rating/cvss3_formulas.rb +103 -0
- data/lib/cvss_rating/cvss3_metrics.rb +52 -0
- data/lib/cvss_rating/cvss3_vectors.rb +551 -0
- data/lib/cvss_rating/version.rb +1 -1
- data/test/cvss2_rating_test.rb +1 -1
- data/test/cvss3_rating_test.rb +235 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba239c3a20044c1f0bdec1bf20040f292fc58a0a
|
4
|
+
data.tar.gz: dd3f4a378df8d13d73240ba8ec36dcb4a20c0a63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c09e29ab6844f87a3279fec34da5ec3bbdc7c68b9dd2f583745f214feeffab34e6d35c70c3ac99b2a67dd2b760ce3bed39da5c0689f37f0d21a36a50bf7325d
|
7
|
+
data.tar.gz: 80391b4cc42fa467640cacc70dd06af7ee5a413abefa1410d234a0ce81ab9093e6c9914ac33f26aa0bc733760c3a20c637aad19d79dce1e74da2bc2cfd9c8478
|
data/README.md
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/mort666/cvss_rating)
|
4
4
|
|
5
|
-
Implements
|
5
|
+
Implements vulnerability scoring system CVSS versions 2.0 and 3.0.
|
6
|
+
|
7
|
+
More information on the standard is available at [https://www.first.org/cvss](https://www.first.org/cvss)
|
6
8
|
|
7
9
|
## Installation
|
8
10
|
|
@@ -20,10 +22,37 @@ Or install it yourself as:
|
|
20
22
|
|
21
23
|
## Usage
|
22
24
|
|
23
|
-
|
25
|
+
The following is basic usage to handle a CVSS 2.0 vector:
|
26
|
+
|
27
|
+
cvs = Cvss2::Rating.new
|
28
|
+
cvss.parse("AV:N/AC:M/Au:N/C:P/I:P/A:P")
|
29
|
+
|
30
|
+
# Calculate overallscore
|
31
|
+
cvss.overallscore
|
32
|
+
|
33
|
+
The following is basic usage to handle a CVSS 3.0 vector:
|
34
|
+
|
35
|
+
cvss = Cvss3::Rating.new
|
36
|
+
cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
|
37
|
+
|
38
|
+
# Calculate Base Score (returns array of score and risk level)
|
39
|
+
cvss.cvss_base_score
|
40
|
+
|
41
|
+
# Calculate Temporal Score (returns array of score and risk level)
|
42
|
+
cvss.cvss_temporal_score
|
43
|
+
|
44
|
+
# Calculate Environmental Score (returns array of score and risk level)
|
45
|
+
cvss.cvss_environmental_score
|
46
|
+
|
47
|
+
Check out the unit tests for more examples of usage.
|
24
48
|
|
25
49
|
## TODO
|
26
50
|
|
27
|
-
* CVSS 3.0 Support
|
28
51
|
* Code and API clean up
|
29
52
|
* More Unit Tests
|
53
|
+
|
54
|
+
## License
|
55
|
+
|
56
|
+
Copyright (c) Stephen Kapp 2015.
|
57
|
+
|
58
|
+
Released under the MIT License
|
data/cvss_rating.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Stephen Kapp"]
|
10
10
|
spec.email = ["mort666@virus.org"]
|
11
11
|
spec.summary = %q{CVSS Risk Rating Calculation and Vector parsing}
|
12
|
-
spec.description = %q{CVSS Risk Rating Calculation and Vector parsing, implements CVSS 2.0 rating}
|
12
|
+
spec.description = %q{CVSS Risk Rating Calculation and Vector parsing, implements CVSS 2.0 & 3.0 rating}
|
13
13
|
spec.homepage = "https://github.com/mort666/cvss_rating"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
data/lib/cvss3_rating.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# @author Stephen Kapp
|
2
|
+
|
3
|
+
require "cvss_rating/version"
|
4
|
+
require "cvss_rating/cvss3_formulas"
|
5
|
+
require "cvss_rating/cvss3_metrics"
|
6
|
+
require "cvss_rating/cvss3_vectors"
|
7
|
+
|
8
|
+
module Cvss3
|
9
|
+
class Rating
|
10
|
+
attr_accessor :exploitability, :base, :impact, :temporal, :environmental
|
11
|
+
|
12
|
+
include Cvss3Vectors
|
13
|
+
|
14
|
+
#
|
15
|
+
# Initialize the object, creates a clean initialized Cvss3::Rating object
|
16
|
+
#
|
17
|
+
# @param list [Hash] list of CVSS 3.0 attributes to be used during initialization
|
18
|
+
#
|
19
|
+
|
20
|
+
def initialize(attributes = {})
|
21
|
+
init
|
22
|
+
|
23
|
+
attributes.each do |name, value|
|
24
|
+
send("#{name}=", value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
#
|
30
|
+
# Takes score and determines risk level from None to Critical
|
31
|
+
#
|
32
|
+
# @param score [Float] risk score to be converted to risk level
|
33
|
+
# @return [String] risk level based on score
|
34
|
+
|
35
|
+
def risk_score(score)
|
36
|
+
risk_score = case score
|
37
|
+
when 0.0
|
38
|
+
"None"
|
39
|
+
when 0.1..3.9
|
40
|
+
"Low"
|
41
|
+
when 4.0..6.9
|
42
|
+
"Medium"
|
43
|
+
when 7.0..8.9
|
44
|
+
"High"
|
45
|
+
when 9.0..10.0
|
46
|
+
"Critical"
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
# Calculate the CVSS 3.0 Base Score
|
55
|
+
#
|
56
|
+
# @return [Array] the CVSS 3.0 Base score with its risk level
|
57
|
+
|
58
|
+
def cvss_base_score
|
59
|
+
@exploitability = ::Cvss3::Formulas.new.exploitability_sub_score(@av, @ac, @pr, @ui)
|
60
|
+
|
61
|
+
@impact = ::Cvss3::Formulas.new.impact_sub_score_base(@ai, @ci, @ii)
|
62
|
+
|
63
|
+
@base = ::Cvss3::Formulas.new.cvss_base_formula(@impact, @sc, @exploitability)
|
64
|
+
|
65
|
+
@base_level = risk_score(@base)
|
66
|
+
|
67
|
+
return @base, @base_level
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
#
|
72
|
+
# Calculate the CVSS 3.0 Temporal Score
|
73
|
+
#
|
74
|
+
# @return [Array] the CVSS 3.0 Temporal score with its risk level
|
75
|
+
|
76
|
+
def cvss_temporal_score
|
77
|
+
@temporal = ::Cvss3::Formulas.new.cvss_temporal_formula(@base, @ex, @rl, @rc)
|
78
|
+
|
79
|
+
@temporal_level = risk_score(@temporal)
|
80
|
+
|
81
|
+
return @temporal, @temporal_level
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
#
|
86
|
+
# Calculate the CVSS 3.0 Temporal Score
|
87
|
+
#
|
88
|
+
# @return [Array] the CVSS 3.0 Temporal score with its risk level
|
89
|
+
|
90
|
+
def cvss_environmental_score
|
91
|
+
exploitability_sub_score_value_modified = ::Cvss3::Formulas.new.exploitability_sub_score_modified(self.mav(true),
|
92
|
+
self.mac(true), self.mpr(true), self.mui(true))
|
93
|
+
|
94
|
+
impact_sub_score_value_modified = ::Cvss3::Formulas.new.impact_sub_score_modified_base(self.ma(true), self.mc(true),
|
95
|
+
self.mi(true), @cr, @ir, @ar)
|
96
|
+
|
97
|
+
@environmental = ::Cvss3::Formulas.new.cvss_environmental_formula(impact_sub_score_value_modified,
|
98
|
+
exploitability_sub_score_value_modified,
|
99
|
+
@ex, @rl, @rc, self.ms(true))
|
100
|
+
|
101
|
+
@environmental_level = risk_score(@environmental)
|
102
|
+
|
103
|
+
return @environmental, @environmental_level
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Cvss3
|
2
|
+
class Formulas
|
3
|
+
EXPLOITABILITY_COEFFICIENT = 8.22
|
4
|
+
IMPACT_COEFFICIENT = 6.42
|
5
|
+
IMPACT_MOD_COEFFICIENT = 7.52
|
6
|
+
|
7
|
+
def exploitability_sub_score(attack_vector_value, attack_complexity_value, privileges_required_value, user_interaction_value)
|
8
|
+
|
9
|
+
exploitability_sub_score_value = EXPLOITABILITY_COEFFICIENT * attack_vector_value * attack_complexity_value * privileges_required_value * user_interaction_value
|
10
|
+
|
11
|
+
return exploitability_sub_score_value
|
12
|
+
end
|
13
|
+
|
14
|
+
def exploitability_sub_score_modified(attack_vector_value_modified, attack_complexity_value_modified,
|
15
|
+
privileges_required_value_modified, user_interaction_value_modified)
|
16
|
+
|
17
|
+
exploitability_sub_score_value_modified = EXPLOITABILITY_COEFFICIENT * attack_vector_value_modified * attack_complexity_value_modified * privileges_required_value_modified * user_interaction_value_modified
|
18
|
+
|
19
|
+
return exploitability_sub_score_value_modified
|
20
|
+
end
|
21
|
+
|
22
|
+
def impact_sub_score_base(availability_value, confidentiality_value, integrity_value)
|
23
|
+
|
24
|
+
impact_sub_score_value = 1 - ((1 - confidentiality_value) * (1 - integrity_value) * (1 - availability_value))
|
25
|
+
|
26
|
+
return impact_sub_score_value
|
27
|
+
end
|
28
|
+
|
29
|
+
def impact_sub_score_modified_base(availability_value_modified, confidentiality_value_modified, integrity_value_modified,
|
30
|
+
confidentiality_requirement_value, integrity_requirement_value, availability_requirement_value)
|
31
|
+
|
32
|
+
impact_sub_score_value_modified = min(0.915, 1 - (1 - confidentiality_value_modified * confidentiality_requirement_value) * (1 - integrity_value_modified * integrity_requirement_value) * (1 - availability_value_modified * availability_requirement_value))
|
33
|
+
|
34
|
+
return impact_sub_score_value_modified
|
35
|
+
end
|
36
|
+
|
37
|
+
def cvss_base_formula(impact_sub_score_value, scope_value, exploitability_sub_score_value)
|
38
|
+
|
39
|
+
if scope_value == "unchanged"
|
40
|
+
impact_value = IMPACT_COEFFICIENT * impact_sub_score_value
|
41
|
+
cvss_base_value = min(10, impact_value + exploitability_sub_score_value)
|
42
|
+
elsif scope_value == "changed"
|
43
|
+
impact_value = IMPACT_MOD_COEFFICIENT * (impact_sub_score_value - 0.029) - 3.25 * ((impact_sub_score_value - 0.02) ** 15)
|
44
|
+
cvss_base_value = min(10, 1.08 * (impact_value + exploitability_sub_score_value))
|
45
|
+
end
|
46
|
+
|
47
|
+
if impact_sub_score_value <= 0
|
48
|
+
cvss_base_value = 0.0
|
49
|
+
else
|
50
|
+
cvss_base_value = cvss_base_value.ceil2(1)
|
51
|
+
end
|
52
|
+
|
53
|
+
return cvss_base_value
|
54
|
+
end
|
55
|
+
|
56
|
+
def cvss_temporal_formula(cvss_base_value, exploit_code_maturity_value, remediation_level_value, report_confidence_value)
|
57
|
+
|
58
|
+
cvss_temporal_value = cvss_base_value * exploit_code_maturity_value * remediation_level_value * \
|
59
|
+
report_confidence_value
|
60
|
+
|
61
|
+
cvss_temporal_value = cvss_temporal_value.ceil2(1)
|
62
|
+
|
63
|
+
return cvss_temporal_value
|
64
|
+
end
|
65
|
+
|
66
|
+
def cvss_environmental_formula(impact_sub_score_value_modified, exploitability_sub_score_value_modified,
|
67
|
+
exploit_code_maturity_value, remediation_level_value, report_confidence_value, scope_value_modified)
|
68
|
+
|
69
|
+
if scope_value_modified == "unchanged"
|
70
|
+
impact_value_modified = IMPACT_COEFFICIENT * impact_sub_score_value_modified
|
71
|
+
temp_score = min(10, impact_value_modified + exploitability_sub_score_value_modified)
|
72
|
+
temp_score2 = temp_score.ceil2(1)
|
73
|
+
temp_score3 = temp_score2 * exploit_code_maturity_value * remediation_level_value * report_confidence_value
|
74
|
+
elsif scope_value_modified == "changed"
|
75
|
+
impact_value_modified = IMPACT_MOD_COEFFICIENT * (impact_sub_score_value_modified - 0.029) - 3.25 * ((impact_sub_score_value_modified - 0.02) ** 15)
|
76
|
+
temp_score = min(10, 1.08 * (impact_value_modified + exploitability_sub_score_value_modified))
|
77
|
+
temp_score2 = temp_score.ceil2(1)
|
78
|
+
temp_score3 = temp_score2 * exploit_code_maturity_value * remediation_level_value * report_confidence_value
|
79
|
+
end
|
80
|
+
|
81
|
+
if impact_sub_score_value_modified <= 0
|
82
|
+
cvss_environmental_value = 0.0
|
83
|
+
else
|
84
|
+
cvss_environmental_value = temp_score3.ceil2(1)
|
85
|
+
end
|
86
|
+
|
87
|
+
return cvss_environmental_value
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def min(*values)
|
92
|
+
values.min
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
class Float
|
99
|
+
def ceil2(exp = 0)
|
100
|
+
multiplier = 10 ** exp
|
101
|
+
((self * multiplier).ceil).to_f/multiplier.to_f
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Cvss3
|
2
|
+
class Metrics
|
3
|
+
# Base Metrics
|
4
|
+
ATTACK_VECTOR = { :physical => 0.2, :local => 0.55, :adjacent_network => 0.62, :network => 0.85, :not_defined => 0.85 }
|
5
|
+
ATTACK_COMPLEXITY = { :high => 0.44, :low => 0.77, :not_defined => 0.77 }
|
6
|
+
|
7
|
+
PRIVILEGE_REQUIRED = { :not_defined => 0.85, :none => 0.85, :low => 0.62, :high => 0.27 }
|
8
|
+
PRIVILEGE_REQUIRED_CHANGED = { :not_defined => 0.85, :none => 0.85, :low => 0.68, :high => 0.50 }
|
9
|
+
|
10
|
+
USER_INTERACTION = {:not_defined => 0.85, :none => 0.85, :required => 0.62 }
|
11
|
+
|
12
|
+
CIA_IMPACT = { :none => 0.0, :low => 0.22, :high => 0.56, :not_defined => 0.56 }
|
13
|
+
|
14
|
+
# Environmental Metrics
|
15
|
+
CIA_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.50, :not_defined => 1.0 }
|
16
|
+
|
17
|
+
# Temporal Metrics
|
18
|
+
EXPLOITABILITY = { :unproven => 0.91, :poc => 0.94, :functional => 0.97, :high => 1.0, :not_defined => 1.0 }
|
19
|
+
|
20
|
+
REMEDIATION_LEVEL = { :official => 0.95, :temporary => 0.96, :workaround => 0.97, :unavailable => 1.0, :not_defined => 1.0 }
|
21
|
+
|
22
|
+
REPORT_CONFIDENCE = { :unknown => 0.92, :reasonable => 0.96, :confirmed => 1.0, :not_defined => 1.0 }
|
23
|
+
|
24
|
+
# Key Lookup values
|
25
|
+
|
26
|
+
ATTACK_VECTOR_KEY = { :physical => 'P', :local => 'L', :adjacent_network => 'A', :network => 'N' }
|
27
|
+
ATTACK_COMPLEXITY_KEY = { :high => 'H', :low => 'L' }
|
28
|
+
PRIVILEGE_REQUIRED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
|
29
|
+
PRIVILEGE_REQUIRED_CHANGED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
|
30
|
+
USER_INTERACTION_KEY = { :none => 'N', :required => 'R' }
|
31
|
+
|
32
|
+
SCOPE_KEY = { :changed => 'C', :unchanged => 'U' }
|
33
|
+
|
34
|
+
CIA_IMPACT_KEY = { :none => 'N', :low => 'L', :high => 'H' }
|
35
|
+
|
36
|
+
CIA_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
37
|
+
|
38
|
+
EXPLOITABILITY_KEY = { :unproven => 'U', :poc => 'P', :functional => 'F', :high => 'H', :not_defined => 'ND' }
|
39
|
+
REMEDIATION_LEVEL_KEY = { :official => 'O', :temporary => "T", :workaround => 'W', :unavailable => 'U', :not_defined => 'ND' }
|
40
|
+
REPORT_CONFIDENCE_KEY = { :unknown => 'U', :reasonable => 'R', :confirmed => 'C', :not_defined => 'ND' }
|
41
|
+
|
42
|
+
MODIFIED_ATTACK_VECTOR_KEY = { :physical => 'P', :local => 'L', :adjacent_network => 'A', :network => 'N' }
|
43
|
+
MODIFIED_ATTACK_COMPLEXITY_KEY = { :high => 'H', :low => 'L' }
|
44
|
+
MODIFIED_PRIVILEGE_REQUIRED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
|
45
|
+
MODIFIED_PRIVILEGE_REQUIRED_CHANGED_KEY = { :none => 'N', :low => 'L', :high => 'H' }
|
46
|
+
MODIFIED_USER_INTERACTION_KEY = { :none => 'N', :required => 'R' }
|
47
|
+
|
48
|
+
MODIFIED_SCOPE_KEY = { :changed => 'C', :unchanged => 'U' }
|
49
|
+
|
50
|
+
MODIFIED_CIA_IMPACT_KEY = { :none => 'N', :low => 'L', :high => 'H' }
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,551 @@
|
|
1
|
+
module Cvss3Vectors
|
2
|
+
attr_reader :av, :ac, :ui, :sc, :ci, :ai, :ii, :ex, :rl, :rc, :pr, :td, :cr, :ir
|
3
|
+
|
4
|
+
VECTORS = {
|
5
|
+
"cvss" => "cvss3=",
|
6
|
+
"av" => "av=",
|
7
|
+
"ac" => "ac=",
|
8
|
+
"ui" => "ui=",
|
9
|
+
"s" => "sc=",
|
10
|
+
"c" => "ci=",
|
11
|
+
"i" => "ii=",
|
12
|
+
"a" => "ai=",
|
13
|
+
"e" => "ex=",
|
14
|
+
"rl" => "rl=",
|
15
|
+
"rc" => "rc=",
|
16
|
+
"pr" => "pr=",
|
17
|
+
"cr" => "cr=",
|
18
|
+
"ir" => "ir=",
|
19
|
+
"ar" => "ar=",
|
20
|
+
"mav" => "mav=",
|
21
|
+
"mac" => "mac=",
|
22
|
+
"ms" => "ms=",
|
23
|
+
"mpr" => "mpr=",
|
24
|
+
"mui" => "mui=",
|
25
|
+
"mc" => "mc=",
|
26
|
+
"mi" => "mi=",
|
27
|
+
"ma" => "ma="
|
28
|
+
}
|
29
|
+
|
30
|
+
def parse(vector)
|
31
|
+
string = vector.split("/")
|
32
|
+
len = string.length
|
33
|
+
|
34
|
+
init
|
35
|
+
|
36
|
+
@originalkey = vector
|
37
|
+
|
38
|
+
string.each do |section|
|
39
|
+
tmp = section.split(":")
|
40
|
+
send(VECTORS[tmp[0].downcase].to_sym, tmp[1])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_key
|
45
|
+
@key = "AV:%s/AC:%s/PR:%s/UI:%s/C:%s/I:%s/A:%s" % [ self.av,
|
46
|
+
self.ac, self.pr, self.ui,
|
47
|
+
self.ci, self.ii, self.ai]
|
48
|
+
|
49
|
+
@key += "/E:%s" % self.ex if !@ex.nil?
|
50
|
+
@key += "/RL:%s" % self.rl if !@rl.nil?
|
51
|
+
@key += "/RC:%s" % self.rc if !@rc.nil?
|
52
|
+
|
53
|
+
@key += "/CR:%s" % self.cr if !@cr.nil?
|
54
|
+
@key += "/IR:%s" % self.ir if !@ir.nil?
|
55
|
+
@key += "/AR:%s" % self.ar if !@ar.nil?
|
56
|
+
|
57
|
+
@key += "/MAV:%s" % self.mav if !@mav.nil?
|
58
|
+
@key += "/MAC:%s" % self.mac if !@mac.nil?
|
59
|
+
@key += "/MPR:%s" % self.mpr if !@mpr.nil?
|
60
|
+
@key += "/MUI:%s" % self.mui if !@mui.nil?
|
61
|
+
@key += "/MS:%s" % self.ms if !@ms.nil?
|
62
|
+
|
63
|
+
@key += "/MC:%s" % self.mc if !@mc.nil?
|
64
|
+
@key += "/MI:%s" % self.mi if !@mi.nil?
|
65
|
+
@key += "/MA:%s" % self.ma if !@ma.nil?
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def key
|
70
|
+
self.set_key
|
71
|
+
return @key
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_key(vector, value)
|
75
|
+
get_key = eval("::Cvss3::Metrics::" + vector + "_KEY")[(eval("::Cvss3::Metrics::" + vector).select { |k,v| v == value }).keys[0]]
|
76
|
+
end
|
77
|
+
|
78
|
+
def cvss3=(cvss3)
|
79
|
+
if cvss3 != "3.0"
|
80
|
+
raise "Bad CVSS 3.0 Vector String"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def av=(av)
|
85
|
+
@av = case av
|
86
|
+
when "physical", "P"
|
87
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:physical]
|
88
|
+
when "local", "L"
|
89
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:local]
|
90
|
+
when "adjacent network", "A"
|
91
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:adjacent_network]
|
92
|
+
when "network", "N"
|
93
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:network]
|
94
|
+
else
|
95
|
+
raise "Bad Argument"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def av
|
100
|
+
av = get_key("ATTACK_VECTOR", @av) if !@av.nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
def ac=(ac)
|
104
|
+
@ac = case ac
|
105
|
+
when "high", "H"
|
106
|
+
::Cvss3::Metrics::ATTACK_COMPLEXITY[:high]
|
107
|
+
when "low", "L"
|
108
|
+
::Cvss3::Metrics::ATTACK_COMPLEXITY[:low]
|
109
|
+
else
|
110
|
+
raise "Bad Argument"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def ac
|
115
|
+
ac = get_key("ATTACK_COMPLEXITY", @ac) if !@ac.nil?
|
116
|
+
end
|
117
|
+
|
118
|
+
def ui=(ui)
|
119
|
+
@ui = case ui
|
120
|
+
when "none", "N"
|
121
|
+
::Cvss3::Metrics::USER_INTERACTION[:none]
|
122
|
+
when "required", "R"
|
123
|
+
::Cvss3::Metrics::USER_INTERACTION[:required]
|
124
|
+
else
|
125
|
+
raise "Bad Argument"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def ui
|
130
|
+
ui = get_key("USER_INTERACTION", @ui) if !@ui.nil?
|
131
|
+
end
|
132
|
+
|
133
|
+
def pr=(pr)
|
134
|
+
@pr = case pr
|
135
|
+
when "none", "N"
|
136
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED[:none]
|
137
|
+
when "low", "L"
|
138
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED[:low]
|
139
|
+
when "high", "H"
|
140
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED[:high]
|
141
|
+
else
|
142
|
+
raise "Bad Argument"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def pr
|
147
|
+
if @sc == "changed"
|
148
|
+
pr = get_key("PRIVILEGE_REQUIRED_CHANGED", @pr) if !@pr.nil?
|
149
|
+
else
|
150
|
+
pr = get_key("PRIVILEGE_REQUIRED", @pr) if !@pr.nil?
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def sc=(sc)
|
155
|
+
@sc = case sc
|
156
|
+
when "changed", "C"
|
157
|
+
"changed"
|
158
|
+
when "unchanged", "U"
|
159
|
+
"unchanged"
|
160
|
+
else
|
161
|
+
raise "Bad Argument"
|
162
|
+
end
|
163
|
+
|
164
|
+
if @sc == "changed"
|
165
|
+
@pr = case get_key("PRIVILEGE_REQUIRED", @pr).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", @pr) : get_key("PRIVILEGE_REQUIRED", @pr)
|
166
|
+
when "none", "N",
|
167
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:none]
|
168
|
+
when "low", "L"
|
169
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:low]
|
170
|
+
when "high", "H"
|
171
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:high]
|
172
|
+
else
|
173
|
+
raise "Bad Argument"
|
174
|
+
end
|
175
|
+
else
|
176
|
+
self.pr = get_key("PRIVILEGE_REQUIRED", @pr).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", @pr) : get_key("PRIVILEGE_REQUIRED", @pr)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def sc
|
181
|
+
sc = ::Cvss3::Metrics::SCOPE_KEY[@sc.to_sym] if !@sc.nil?
|
182
|
+
end
|
183
|
+
|
184
|
+
def ci=(ci)
|
185
|
+
@ci = case ci
|
186
|
+
when "none", "N"
|
187
|
+
::Cvss3::Metrics::CIA_IMPACT[:none]
|
188
|
+
when "low", "L"
|
189
|
+
::Cvss3::Metrics::CIA_IMPACT[:low]
|
190
|
+
when "high", "H"
|
191
|
+
::Cvss3::Metrics::CIA_IMPACT[:high]
|
192
|
+
else
|
193
|
+
raise "Bad Argument"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def ci
|
198
|
+
ci = get_key("CIA_IMPACT", @ci) if !@ci.nil?
|
199
|
+
end
|
200
|
+
|
201
|
+
def ii=(ii)
|
202
|
+
@ii = case ii
|
203
|
+
when "none", "N"
|
204
|
+
::Cvss3::Metrics::CIA_IMPACT[:none]
|
205
|
+
when "low", "L"
|
206
|
+
::Cvss3::Metrics::CIA_IMPACT[:low]
|
207
|
+
when "high", "H"
|
208
|
+
::Cvss3::Metrics::CIA_IMPACT[:high]
|
209
|
+
else
|
210
|
+
raise "Bad Argument"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def ii
|
215
|
+
ii = get_key("CIA_IMPACT", @ii) if !@ii.nil?
|
216
|
+
end
|
217
|
+
|
218
|
+
def ai=(ai)
|
219
|
+
@ai = case ai
|
220
|
+
when "none", "N"
|
221
|
+
::Cvss3::Metrics::CIA_IMPACT[:none]
|
222
|
+
when "low", "L"
|
223
|
+
::Cvss3::Metrics::CIA_IMPACT[:low]
|
224
|
+
when "high", "H"
|
225
|
+
::Cvss3::Metrics::CIA_IMPACT[:high]
|
226
|
+
else
|
227
|
+
raise "Bad Argument"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def ai
|
232
|
+
ai = get_key("CIA_IMPACT", @ai) if !@ai.nil?
|
233
|
+
end
|
234
|
+
|
235
|
+
def mav=(mav)
|
236
|
+
@mav = case mav
|
237
|
+
when "physical", "P"
|
238
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:physical]
|
239
|
+
when "local", "L"
|
240
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:local]
|
241
|
+
when "adjacent network", "A"
|
242
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:adjacent_network]
|
243
|
+
when "network", "N"
|
244
|
+
::Cvss3::Metrics::ATTACK_VECTOR[:network]
|
245
|
+
when "not_defined", "ND"
|
246
|
+
nil
|
247
|
+
else
|
248
|
+
raise "Bad Argument"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def mav(raw=false)
|
253
|
+
if raw
|
254
|
+
@mav ||= @av
|
255
|
+
else
|
256
|
+
mav = get_key("ATTACK_VECTOR", @mav) if !@mav.nil?
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def mac=(mac)
|
261
|
+
@mac = case mac
|
262
|
+
when "high", "H"
|
263
|
+
::Cvss3::Metrics::ATTACK_COMPLEXITY[:high]
|
264
|
+
when "low", "L"
|
265
|
+
::Cvss3::Metrics::ATTACK_COMPLEXITY[:low]
|
266
|
+
when "not_defined", "ND"
|
267
|
+
nil
|
268
|
+
else
|
269
|
+
raise "Bad Argument"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def mac(raw=false)
|
274
|
+
if raw
|
275
|
+
@mac ||= @ac
|
276
|
+
else
|
277
|
+
mac = get_key("ATTACK_COMPLEXITY", @mac) if !@mac.nil?
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def mui=(mui)
|
282
|
+
@mui = case mui
|
283
|
+
when "none", "N"
|
284
|
+
::Cvss3::Metrics::USER_INTERACTION[:none]
|
285
|
+
when "required", "R"
|
286
|
+
::Cvss3::Metrics::USER_INTERACTION[:required]
|
287
|
+
when "not_defined", "ND"
|
288
|
+
nil
|
289
|
+
else
|
290
|
+
raise "Bad Argument"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def mui(raw=false)
|
295
|
+
if raw
|
296
|
+
@mui ||= @ui
|
297
|
+
else
|
298
|
+
mui = get_key("USER_INTERACTION", @mui) if !@mui.nil?
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def mpr=(mpr)
|
303
|
+
@mpr = case mpr
|
304
|
+
when "none", "N"
|
305
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED[:none]
|
306
|
+
when "low", "L"
|
307
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED[:low]
|
308
|
+
when "high", "H"
|
309
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED[:high]
|
310
|
+
when "not_defined", "ND"
|
311
|
+
nil
|
312
|
+
else
|
313
|
+
raise "Bad Argument"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def mpr(raw=false)
|
318
|
+
if raw
|
319
|
+
@mpr ||= @pr
|
320
|
+
else
|
321
|
+
if @ms == "changed"
|
322
|
+
mpr = get_key("PRIVILEGE_REQUIRED_CHANGED", @mpr) if !@mpr.nil?
|
323
|
+
else
|
324
|
+
mpr = get_key("PRIVILEGE_REQUIRED", @mpr) if !@mpr.nil?
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def ms=(ms)
|
330
|
+
@ms = case ms
|
331
|
+
when "changed", "C"
|
332
|
+
"changed"
|
333
|
+
when "unchanged", "U"
|
334
|
+
"unchanged"
|
335
|
+
when "not_defined", "ND"
|
336
|
+
nil
|
337
|
+
else
|
338
|
+
raise "Bad Argument"
|
339
|
+
end
|
340
|
+
|
341
|
+
if @ms == "changed"
|
342
|
+
@mpr = case get_key("PRIVILEGE_REQUIRED", self.mpr(true)).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", self.mpr(true)) : get_key("PRIVILEGE_REQUIRED", self.mpr(true))
|
343
|
+
when "none", "N",
|
344
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:none]
|
345
|
+
when "low", "L"
|
346
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:low]
|
347
|
+
when "high", "H"
|
348
|
+
::Cvss3::Metrics::PRIVILEGE_REQUIRED_CHANGED[:high]
|
349
|
+
else
|
350
|
+
raise "Bad Argument"
|
351
|
+
end
|
352
|
+
else
|
353
|
+
self.mpr = get_key("PRIVILEGE_REQUIRED", self.mpr(true)).nil? ? get_key("PRIVILEGE_REQUIRED_CHANGED", self.mpr(true)) : get_key("PRIVILEGE_REQUIRED", self.mpr(true))
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def ms(raw=false)
|
358
|
+
if raw
|
359
|
+
@ms ||= @sc
|
360
|
+
else
|
361
|
+
if @ms.nil?
|
362
|
+
ms = ::Cvss3::Metrics::SCOPE_KEY[@sc.to_sym] if !@sc.nil?
|
363
|
+
else
|
364
|
+
ms = ::Cvss3::Metrics::SCOPE_KEY[@ms.to_sym] if !@ms.nil?
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def mc=(mc)
|
370
|
+
@mc = case mc
|
371
|
+
when "none", "N"
|
372
|
+
::Cvss3::Metrics::CIA_IMPACT[:none]
|
373
|
+
when "low", "L"
|
374
|
+
::Cvss3::Metrics::CIA_IMPACT[:low]
|
375
|
+
when "high", "H"
|
376
|
+
::Cvss3::Metrics::CIA_IMPACT[:high]
|
377
|
+
when "not_defined", "ND"
|
378
|
+
nil
|
379
|
+
else
|
380
|
+
raise "Bad Argument"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def mc(raw=false)
|
385
|
+
if raw
|
386
|
+
@mv ||= @ci
|
387
|
+
else
|
388
|
+
mc = get_key("CIA_IMPACT", @mc) if !@mc.nil?
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def mi=(mi)
|
393
|
+
@mi = case mi
|
394
|
+
when "none", "N"
|
395
|
+
::Cvss3::Metrics::CIA_IMPACT[:none]
|
396
|
+
when "low", "L"
|
397
|
+
::Cvss3::Metrics::CIA_IMPACT[:low]
|
398
|
+
when "high", "H"
|
399
|
+
::Cvss3::Metrics::CIA_IMPACT[:high]
|
400
|
+
when "not_defined", "ND"
|
401
|
+
nil
|
402
|
+
else
|
403
|
+
raise "Bad Argument"
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def mi(raw=false)
|
408
|
+
if raw
|
409
|
+
@mi ||= @ii
|
410
|
+
else
|
411
|
+
mi = get_key("CIA_IMPACT", @mi) if !@mi.nil?
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
def ma=(ma)
|
416
|
+
@ma = case ma
|
417
|
+
when "none", "N"
|
418
|
+
::Cvss3::Metrics::CIA_IMPACT[:none]
|
419
|
+
when "low", "L"
|
420
|
+
::Cvss3::Metrics::CIA_IMPACT[:low]
|
421
|
+
when "high", "H"
|
422
|
+
::Cvss3::Metrics::CIA_IMPACT[:high]
|
423
|
+
when "not_defined", "ND"
|
424
|
+
nil
|
425
|
+
else
|
426
|
+
raise "Bad Argument"
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def ma(raw=false)
|
431
|
+
if raw
|
432
|
+
@ma ||= @ai
|
433
|
+
else
|
434
|
+
ma = get_key("CIA_IMPACT", @ma) if !@ma.nil?
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
def ex=(ex)
|
439
|
+
@ex = case ex
|
440
|
+
when "unproven", "U" then ::Cvss3::Metrics::EXPLOITABILITY[:unproven]
|
441
|
+
when "proof-of-concept", "P", "POC" then ::Cvss3::Metrics::EXPLOITABILITY[:poc]
|
442
|
+
when "functional", "F" then ::Cvss3::Metrics::EXPLOITABILITY[:functional]
|
443
|
+
when "high", "H" then ::Cvss3::Metrics::EXPLOITABILITY[:high]
|
444
|
+
when "not defined", "ND", "X" then ::Cvss3::Metrics::EXPLOITABILITY[:not_defined]
|
445
|
+
else
|
446
|
+
raise "Bad Argument"
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
def ex
|
451
|
+
ex = get_key("EXPLOITABILITY", @ex) if !@ex.nil?
|
452
|
+
end
|
453
|
+
|
454
|
+
def rl=(rl)
|
455
|
+
@rl = case rl
|
456
|
+
when "official-fix", "O" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:official]
|
457
|
+
when "temporary-fix", "T", "TF" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:temporary]
|
458
|
+
when "workaround", "W" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:workaround]
|
459
|
+
when "unavailable", "U" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:unavailable]
|
460
|
+
when "not defined", "ND", "X" then ::Cvss3::Metrics::REMEDIATION_LEVEL[:not_defined]
|
461
|
+
else
|
462
|
+
raise "Bad Argument"
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
def rl
|
467
|
+
rl = get_key("REMEDIATION_LEVEL", @rl) if !@rl.nil?
|
468
|
+
end
|
469
|
+
|
470
|
+
def rc=(rc)
|
471
|
+
@rc = case rc
|
472
|
+
when "unknown", "U" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:unknown]
|
473
|
+
when "reasonable", "R" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:reasonable]
|
474
|
+
when "confirmed", "C" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:confirmed]
|
475
|
+
when "not defined", "ND", "X" then ::Cvss3::Metrics::REPORT_CONFIDENCE[:not_defined]
|
476
|
+
else
|
477
|
+
raise "Bad Argument"
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def rc
|
482
|
+
rc = get_key("REPORT_CONFIDENCE", @rc) if !@av.nil?
|
483
|
+
end
|
484
|
+
|
485
|
+
def cr=(cr)
|
486
|
+
@cr = case cr
|
487
|
+
when "low", "L" then ::Cvss3::Metrics::CIA_REQUIREMENT[:low]
|
488
|
+
when "medium", "M" then ::Cvss3::Metrics::CIA_REQUIREMENT[:medium]
|
489
|
+
when "high", "H" then ::Cvss3::Metrics::CIA_REQUIREMENT[:high]
|
490
|
+
when "not defined", "ND", "X" then ::Cvss3::Metrics::CIA_REQUIREMENT[:not_defined]
|
491
|
+
else
|
492
|
+
raise "Bad Argument"
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
def cr
|
497
|
+
cr = get_key("CIA_REQUIREMENT", @cr) if !@cr.nil?
|
498
|
+
end
|
499
|
+
|
500
|
+
def ir=(ir)
|
501
|
+
@ir = case ir
|
502
|
+
when "low", "L" then ::Cvss3::Metrics::CIA_REQUIREMENT[:low]
|
503
|
+
when "medium", "M" then ::Cvss3::Metrics::CIA_REQUIREMENT[:medium]
|
504
|
+
when "high", "H" then ::Cvss3::Metrics::CIA_REQUIREMENT[:high]
|
505
|
+
when "not defined", "ND", "X" then ::Cvss3::Metrics::CIA_REQUIREMENT[:not_defined]
|
506
|
+
else
|
507
|
+
raise "Bad Argument"
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
def ir
|
512
|
+
ir = get_key("CIA_REQUIREMENT", @ir) if !@ir.nil?
|
513
|
+
end
|
514
|
+
|
515
|
+
def ar=(ar)
|
516
|
+
@ar = case ar
|
517
|
+
when "low", "L" then ::Cvss3::Metrics::CIA_REQUIREMENT[:low]
|
518
|
+
when "medium", "M" then ::Cvss3::Metrics::CIA_REQUIREMENT[:medium]
|
519
|
+
when "high", "H" then ::Cvss3::Metrics::CIA_REQUIREMENT[:high]
|
520
|
+
when "not defined", "ND", "X" then ::Cvss3::Metrics::CIA_REQUIREMENT[:not_defined]
|
521
|
+
else
|
522
|
+
raise "Bad Argument"
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
def ar
|
527
|
+
ar = get_key("CIA_REQUIREMENT", @ar) if !@ar.nil?
|
528
|
+
end
|
529
|
+
|
530
|
+
|
531
|
+
def init(ex = "ND", rl = "ND", rc = "ND", cd = "ND", td = "ND", cr = "ND", ir = "ND", ar = "ND",
|
532
|
+
mav = "ND", mac = "ND", mpv = "ND", mui = "ND", mc = "ND", mi = "ND", ma = "ND")
|
533
|
+
self.ex = ex
|
534
|
+
self.rl = rl
|
535
|
+
self.rc = rc
|
536
|
+
|
537
|
+
self.cr = cr
|
538
|
+
self.ir = ir
|
539
|
+
self.ar = ar
|
540
|
+
|
541
|
+
self.mav = mav
|
542
|
+
self.mac = mac
|
543
|
+
self.mpr = mpv
|
544
|
+
self.mui = mui
|
545
|
+
|
546
|
+
self.mc = mc
|
547
|
+
self.mi = mi
|
548
|
+
self.ma = ma
|
549
|
+
end
|
550
|
+
|
551
|
+
end
|
data/lib/cvss_rating/version.rb
CHANGED
data/test/cvss2_rating_test.rb
CHANGED
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'active_support'
|
3
|
+
require 'cvss3_rating'
|
4
|
+
|
5
|
+
class Cvss3RatingTest < MiniTest::Test
|
6
|
+
def setup
|
7
|
+
@cvss = Cvss3::Rating.new
|
8
|
+
@cvss.av = "P"
|
9
|
+
@cvss.ac = "H"
|
10
|
+
@cvss.ui = "R"
|
11
|
+
@cvss.pr = "L"
|
12
|
+
@cvss.sc = "C"
|
13
|
+
@cvss.ci = "H"
|
14
|
+
@cvss.ii = "low"
|
15
|
+
@cvss.ai = "N"
|
16
|
+
|
17
|
+
@cvss_2 = Cvss3::Rating.new
|
18
|
+
@cvss_2.av = "P"
|
19
|
+
@cvss_2.ac = "H"
|
20
|
+
@cvss_2.ui = "R"
|
21
|
+
@cvss_2.pr = "H"
|
22
|
+
@cvss_2.sc = "C"
|
23
|
+
@cvss_2.ci = "H"
|
24
|
+
@cvss_2.ii = "low"
|
25
|
+
@cvss_2.ai = "N"
|
26
|
+
@cvss_2.ex = "U"
|
27
|
+
@cvss_2.rl = "O"
|
28
|
+
@cvss_2.rc = "U"
|
29
|
+
@cvss_2.cr = "L"
|
30
|
+
@cvss_2.ir = "L"
|
31
|
+
@cvss_2.ar = "L"
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_cvss_rating_from_vector
|
35
|
+
cvss = Cvss3::Rating.new
|
36
|
+
cvss.parse("AV:P/AC:H/PR:L/UI:R/S:C/C:H/I:L/A:N")
|
37
|
+
|
38
|
+
assert_equal @cvss.ai, cvss.ai
|
39
|
+
|
40
|
+
assert_equal @cvss.ii, cvss.ii
|
41
|
+
|
42
|
+
assert_equal @cvss.av, cvss.av
|
43
|
+
|
44
|
+
assert_equal @cvss.ui, cvss.ui
|
45
|
+
|
46
|
+
assert_equal @cvss.key, cvss.key
|
47
|
+
|
48
|
+
cvss = Cvss3::Rating.new
|
49
|
+
cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
|
50
|
+
|
51
|
+
assert_equal @cvss_2.ai, cvss.ai
|
52
|
+
|
53
|
+
assert_equal @cvss_2.ii, cvss.ii
|
54
|
+
|
55
|
+
assert_equal @cvss_2.av, cvss.av
|
56
|
+
|
57
|
+
assert_equal @cvss_2.key, cvss.key
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_valid_vector
|
61
|
+
cvss = Cvss3::Rating.new
|
62
|
+
|
63
|
+
err = assert_raises RuntimeError do
|
64
|
+
cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:X/A:N")
|
65
|
+
end
|
66
|
+
|
67
|
+
assert_match /Bad Argument/, err.message
|
68
|
+
|
69
|
+
err = assert_raises RuntimeError do
|
70
|
+
cvss.parse("CVSS:9.9/AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:L/A:N")
|
71
|
+
end
|
72
|
+
|
73
|
+
assert_match /Bad CVSS 3.0 Vector String/, err.message
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_cvss_rating_parameters
|
77
|
+
cvss = Cvss3::Rating.new
|
78
|
+
|
79
|
+
cvss.av = "physical"
|
80
|
+
|
81
|
+
assert_equal @cvss.av, cvss.av
|
82
|
+
|
83
|
+
cvss.pr = 'low'
|
84
|
+
|
85
|
+
assert_equal @cvss.pr, cvss.pr
|
86
|
+
|
87
|
+
cvss.ci = 'high'
|
88
|
+
|
89
|
+
assert_equal @cvss.ci, cvss.ci
|
90
|
+
|
91
|
+
cvss.ai = 'none'
|
92
|
+
|
93
|
+
assert_equal @cvss.ai, cvss.ai
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_cvss_risk_rating
|
98
|
+
cvss = Cvss3::Rating.new
|
99
|
+
|
100
|
+
assert_equal "None", cvss.risk_score(0.0)
|
101
|
+
|
102
|
+
assert_equal "Low", cvss.risk_score(2.0)
|
103
|
+
|
104
|
+
assert_equal "Medium", cvss.risk_score(5.1)
|
105
|
+
|
106
|
+
assert_equal "High", cvss.risk_score(7.1)
|
107
|
+
|
108
|
+
assert_equal "Critical", cvss.risk_score(10.0)
|
109
|
+
|
110
|
+
assert_equal nil, cvss.risk_score(11.0)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_base_score
|
114
|
+
cvss = Cvss3::Rating.new
|
115
|
+
cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:N")
|
116
|
+
|
117
|
+
score = cvss.cvss_base_score
|
118
|
+
|
119
|
+
assert_equal 3.9, score[0]
|
120
|
+
|
121
|
+
assert_equal "Low", score[1]
|
122
|
+
|
123
|
+
cvss = Cvss3::Rating.new
|
124
|
+
cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
|
125
|
+
|
126
|
+
score = cvss.cvss_base_score
|
127
|
+
|
128
|
+
assert_equal 5.4, score[0]
|
129
|
+
|
130
|
+
assert_equal "Medium", score[1]
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_temporal_score
|
135
|
+
cvss = Cvss3::Rating.new
|
136
|
+
cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:N")
|
137
|
+
|
138
|
+
cvss.cvss_base_score
|
139
|
+
|
140
|
+
score = cvss.cvss_temporal_score
|
141
|
+
|
142
|
+
assert_equal 3.9, score[0]
|
143
|
+
|
144
|
+
assert_equal "Low", score[1]
|
145
|
+
|
146
|
+
cvss = Cvss3::Rating.new
|
147
|
+
cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
|
148
|
+
|
149
|
+
cvss.cvss_base_score
|
150
|
+
|
151
|
+
score = cvss.cvss_temporal_score
|
152
|
+
|
153
|
+
assert_equal 4.3, score[0]
|
154
|
+
|
155
|
+
assert_equal "Medium", score[1]
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_environmental_score
|
159
|
+
cvss = Cvss3::Rating.new
|
160
|
+
cvss.parse("AV:P/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:N")
|
161
|
+
|
162
|
+
cvss.cvss_base_score
|
163
|
+
|
164
|
+
score = cvss.cvss_environmental_score
|
165
|
+
|
166
|
+
assert_equal 3.9, score[0]
|
167
|
+
|
168
|
+
assert_equal "Low", score[1]
|
169
|
+
|
170
|
+
cvss = Cvss3::Rating.new
|
171
|
+
cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/CR:L/IR:L/AR:L")
|
172
|
+
|
173
|
+
cvss.cvss_base_score
|
174
|
+
|
175
|
+
score = cvss.cvss_environmental_score
|
176
|
+
|
177
|
+
assert_equal 2.4, score[0]
|
178
|
+
|
179
|
+
assert_equal "Low", score[1]
|
180
|
+
|
181
|
+
cvss = Cvss3::Rating.new
|
182
|
+
cvss.parse("AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/IR:L/AR:L/MAV:A/MPR:N")
|
183
|
+
|
184
|
+
cvss.cvss_base_score
|
185
|
+
|
186
|
+
score = cvss.cvss_environmental_score
|
187
|
+
|
188
|
+
assert_equal 4.8, score[0]
|
189
|
+
|
190
|
+
assert_equal "Medium", score[1]
|
191
|
+
|
192
|
+
cvss = Cvss3::Rating.new
|
193
|
+
cvss.parse("CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:C/C:H/I:L/A:N/E:U/RL:O/RC:U/MAV:N/MS:U")
|
194
|
+
|
195
|
+
cvss.cvss_base_score
|
196
|
+
|
197
|
+
score = cvss.cvss_environmental_score
|
198
|
+
|
199
|
+
assert_equal 3.9, score[0]
|
200
|
+
|
201
|
+
assert_equal "Low", score[1]
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_all_scores
|
205
|
+
cvss = Cvss3::Rating.new
|
206
|
+
cvss.parse("AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N/E:X/RL:X/RC:X")
|
207
|
+
|
208
|
+
score = cvss.cvss_base_score
|
209
|
+
|
210
|
+
assert_equal 0.0, score[0]
|
211
|
+
|
212
|
+
score = cvss.cvss_temporal_score
|
213
|
+
|
214
|
+
assert_equal 0.0, score[0]
|
215
|
+
|
216
|
+
score = cvss.cvss_environmental_score
|
217
|
+
|
218
|
+
assert_equal 0.0, score[0]
|
219
|
+
|
220
|
+
cvss.parse("AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:H/E:H/RL:W/RC:U/CR:H/IR:H/AR:M/MAV:L/MAC:L/MPR:H/MUI:N/MS:C/MC:N/MI:H/MA:L")
|
221
|
+
|
222
|
+
score = cvss.cvss_base_score
|
223
|
+
|
224
|
+
assert_equal 5.8, score[0]
|
225
|
+
|
226
|
+
score = cvss.cvss_temporal_score
|
227
|
+
|
228
|
+
assert_equal 5.2, score[0]
|
229
|
+
|
230
|
+
score = cvss.cvss_environmental_score
|
231
|
+
|
232
|
+
assert_equal 7.4, score[0]
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cvss_rating
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Kapp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
description: CVSS Risk Rating Calculation and Vector parsing, implements CVSS 2.0
|
70
|
-
rating
|
70
|
+
& 3.0 rating
|
71
71
|
email:
|
72
72
|
- mort666@virus.org
|
73
73
|
executables: []
|
@@ -82,8 +82,13 @@ files:
|
|
82
82
|
- Rakefile
|
83
83
|
- cvss_rating.gemspec
|
84
84
|
- lib/cvss2_rating.rb
|
85
|
+
- lib/cvss3_rating.rb
|
86
|
+
- lib/cvss_rating/cvss3_formulas.rb
|
87
|
+
- lib/cvss_rating/cvss3_metrics.rb
|
88
|
+
- lib/cvss_rating/cvss3_vectors.rb
|
85
89
|
- lib/cvss_rating/version.rb
|
86
90
|
- test/cvss2_rating_test.rb
|
91
|
+
- test/cvss3_rating_test.rb
|
87
92
|
homepage: https://github.com/mort666/cvss_rating
|
88
93
|
licenses:
|
89
94
|
- MIT
|
@@ -110,3 +115,4 @@ specification_version: 4
|
|
110
115
|
summary: CVSS Risk Rating Calculation and Vector parsing
|
111
116
|
test_files:
|
112
117
|
- test/cvss2_rating_test.rb
|
118
|
+
- test/cvss3_rating_test.rb
|