cvss_rating 0.2.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/mort666/cvss_rating.svg)](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
|