cvss_rating 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +27 -0
- data/Rakefile +22 -0
- data/cvss_rating.gemspec +23 -0
- data/lib/cvss_rating/version.rb +5 -0
- data/lib/cvss_rating.rb +453 -0
- data/test/cvss_rating_test.rb +61 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 86710948607aed7404a2f0fe021a0cb734cf1a6b
|
4
|
+
data.tar.gz: 8a98d94e813c4a0be0afe2b22b5f6fd66f5d5b63
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e1c0f19932a291bb805fd5c784ccc0d685bad189aab48ae5b2f2aed4bd56330c345cd3100a2530d12aff54259ea5499ca048f3137a2447e0c8423a829a860abe
|
7
|
+
data.tar.gz: 77af3c98596f4ad2d7f0a429f8275c7c487c91947ab88eb4a099187e84a0cb145518fc9829726bc6849fb78432957af850299934cce8f371494eff136d7719c6
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Stephen Kapp
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Cvss Rating
|
2
|
+
|
3
|
+
Implements CVSS Risk Rating version 2.0
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'cvss_rating'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install cvss_rating
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Check out the unit tests for examples of usage
|
22
|
+
|
23
|
+
## TODO
|
24
|
+
|
25
|
+
* CVSS 3.0 Support
|
26
|
+
* Code and API clean up
|
27
|
+
* More Unit Tests
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rdoc/task'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the app_version plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the app_version plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Cvss Rating'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
data/cvss_rating.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cvss_rating/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cvss_rating"
|
8
|
+
spec.version = Cvss::Rating::VERSION
|
9
|
+
spec.authors = ["Stephen Kapp"]
|
10
|
+
spec.email = ["mort666@virus.org"]
|
11
|
+
spec.summary = %q{CVSS Risk Rating Calucation and Vector parsing}
|
12
|
+
spec.description = %q{CVSS Risk Rating Calucation and Vector parsing, implements CVSS 2.0 rating}
|
13
|
+
spec.homepage = "https://github.com/mort666/cvss_rating"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "minitest"
|
23
|
+
end
|
data/lib/cvss_rating.rb
ADDED
@@ -0,0 +1,453 @@
|
|
1
|
+
require "cvss_rating/version"
|
2
|
+
|
3
|
+
module Cvss
|
4
|
+
class Rating
|
5
|
+
|
6
|
+
attr_accessor :av, :ac, :au, :ci, :ii, :ai, :ex, :rl, :rc, :cdp, :td, :cr, :ir, :ar
|
7
|
+
attr_accessor :base, :temporal, :overall, :environmental, :impact, :exploitability, :adjimpact, :key
|
8
|
+
|
9
|
+
ACCESS_VECTOR = { :local => 0.395, :adjacent_network => 0.646, :network => 1.0 }
|
10
|
+
ACCESS_COMPLEXITY = { :high => 0.35, :medium => 0.61, :low => 0.71 }
|
11
|
+
AUTHENTICATION = { :none => 0.704, :single => 0.56, :multiple => 0.45 }
|
12
|
+
|
13
|
+
CONFIDENTIALITY_IMPACT = { :none => 0.0, :partial => 0.275, :complete => 0.660 }
|
14
|
+
INTEGRITY_IMPACT = { :none => 0.0, :partial => 0.275, :complete => 0.660 }
|
15
|
+
AVAILABILITY_IMPACT = { :none => 0.0, :partial => 0.275, :complete => 0.660 }
|
16
|
+
|
17
|
+
CONFIDENTIALITY_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.51, :notdefined => -1.0 }
|
18
|
+
INTEGRITY_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.51, :notdefined => -1.0 }
|
19
|
+
AVAILABILITY_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.51, :notdefined => -1.0 }
|
20
|
+
|
21
|
+
EXPLOITABILITY = { :unproven => 0.85, :poc => 0.9, :functional => 0.95, :high => 1.0, :notdefined => -1.0 }
|
22
|
+
REMEDIATION_LEVEL = { :official => 0.87, :temporary => 0.9, :workaround => 0.95, :unavailable => 1.0, :notdefined => -1.0 }
|
23
|
+
REPORT_CONFIDENCE = { :unconfirmed => 0.90, :uncorroborated => 0.95, :confirmed => 1.0, :notdefined => -1.0 }
|
24
|
+
|
25
|
+
COLLATERAL_DAMAGE = { :none => 0.0, :low => 0.1, :low_medium => 0.3, :medium_high => 0.4, :high => 0.5, :notdefined => -1.0 }
|
26
|
+
TARGET_DISTRIBUTION = { :none => 0.0, :low => 0.25, :medium => 0.75, :high => 1.0, :notdefined => -1.0 }
|
27
|
+
|
28
|
+
ACCESS_VECTOR_KEY = { :local => 'L', :adjacent_network => 'A', :network => 'N' }
|
29
|
+
ACCESS_COMPLEXITY_KEY = { :high => 'H', :medium => 'M', :low => 'L' }
|
30
|
+
AUTHENTICATION_KEY = { :none => 'N', :single => 'S', :multiple => 'M' }
|
31
|
+
|
32
|
+
CONFIDENTIALITY_IMPACT_KEY = { :none => 'N', :partial => 'P', :complete => 'C' }
|
33
|
+
INTEGRITY_IMPACT_KEY = { :none => 'N', :partial => 'P', :complete => 'C' }
|
34
|
+
AVAILABILITY_IMPACT_KEY = { :none => 'N', :partial => 'P', :complete => 'C' }
|
35
|
+
|
36
|
+
CONFIDENTIALITY_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
37
|
+
INTEGRITY_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
38
|
+
AVAILABILITY_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
39
|
+
|
40
|
+
EXPLOITABILITY_KEY = { :unproven => 'U', :poc => 'P', :functional => 'F', :high => 'H', :notdefined => 'ND' }
|
41
|
+
REMEDIATION_LEVEL_KEY = { :official => 'OF', :temporary => "TF", :workaround => 'W', :unavailable => 'U', :notdefined => 'ND' }
|
42
|
+
REPORT_CONFIDENCE_KEY = { :unconfirmed => 'UC', :uncorroborated => 'UR', :confirmed => 'C', :notdefined => 'ND' }
|
43
|
+
|
44
|
+
COLLATERAL_DAMAGE_KEY = { :none => 'N', :low => 'L', :low_medium => 'LM', :medium_high => 'MH', :high => 'H', :notdefined => 'ND' }
|
45
|
+
TARGET_DISTRIBUTION_KEY = { :none => 'N', :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
46
|
+
|
47
|
+
def initialize(attributes = {})
|
48
|
+
@base = nil
|
49
|
+
@temporal = nil
|
50
|
+
@environmental = nil
|
51
|
+
|
52
|
+
self.init
|
53
|
+
|
54
|
+
attributes.each do |name, value|
|
55
|
+
send("#{name}=", value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def init(ex = "ND", rl = "ND", rc = "ND", cd = "ND", td = "ND", cr = "ND", ir = "ND", ar = "ND")
|
60
|
+
self.ex = ex
|
61
|
+
self.rl = rl
|
62
|
+
self.rc = rc
|
63
|
+
|
64
|
+
self.cdp = cd
|
65
|
+
self.td = td
|
66
|
+
self.cr = cr
|
67
|
+
self.ir = ir
|
68
|
+
self.ar = ar
|
69
|
+
end
|
70
|
+
|
71
|
+
def scores(av, ac, au, ci, ii, ai, ex = "ND", rl = "ND", rc = "ND", cd = "ND", td = "ND", cr = "ND", ir = "ND", ar = "ND")
|
72
|
+
self.av = av
|
73
|
+
self.ac = ac
|
74
|
+
self.au = au
|
75
|
+
self.ci = ci
|
76
|
+
self.ii = ii
|
77
|
+
self.ai = ai
|
78
|
+
|
79
|
+
self.ex = ex
|
80
|
+
self.rl = rl
|
81
|
+
self.rc = rc
|
82
|
+
|
83
|
+
self.cd = cd
|
84
|
+
self.td = td
|
85
|
+
self.cr = cr
|
86
|
+
self.ir = ir
|
87
|
+
self.ar = ar
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_key(vector, value)
|
91
|
+
get_key = eval(vector + "_KEY")[(eval(vector).select { |k,v| v == value }).keys[0]]
|
92
|
+
end
|
93
|
+
|
94
|
+
def noenvironmental
|
95
|
+
if get_key("COLLATERAL_DAMAGE", @cdp) == "ND" && get_key("TARGET_DISTRIBUTION", @td) == "ND" && get_key("CONFIDENTIALITY_REQUIREMENT", @cr) == "ND" && get_key("INTEGRITY_REQUIREMENT", @ir) == "ND" && get_key("AVAILABILITY_REQUIREMENT", @ar) == "ND"
|
96
|
+
return true
|
97
|
+
else
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def notemporal
|
103
|
+
if get_key("EXPLOITABILITY", @ex) == "ND" && get_key("REMEDIATION_LEVEL", @rl) == "ND" && get_key("REPORT_CONFIDENCE", @rc) == "ND"
|
104
|
+
return true
|
105
|
+
else
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_key
|
111
|
+
@key = "AV:%s/AC:%s/Au:%s/C:%s/I:%s/A:%s" % [ get_key("ACCESS_VECTOR", @av),
|
112
|
+
get_key("ACCESS_COMPLEXITY", @ac),
|
113
|
+
get_key("AUTHENTICATION", @au),
|
114
|
+
get_key("CONFIDENTIALITY_IMPACT", @ci),
|
115
|
+
get_key("INTEGRITY_IMPACT", @ii),
|
116
|
+
get_key("AVAILABILITY_IMPACT", @ai)]
|
117
|
+
|
118
|
+
if !notemporal
|
119
|
+
@key += "/E:%s/RL:%s/RC:%s" % [ get_key("EXPLOITABILITY", @ex),
|
120
|
+
get_key("REMEDIATION_LEVEL", @rl),
|
121
|
+
get_key("REPORT_CONFIDENCE", @rc)]
|
122
|
+
end
|
123
|
+
|
124
|
+
if !noenvironmental
|
125
|
+
@key += "/CDP:%s/TD:%s/CR:%s/IR:%s/AR:%s" % [ get_key("COLLATERAL_DAMAGE", @cdp),
|
126
|
+
get_key("TARGET_DISTRIBUTION", @td),
|
127
|
+
get_key("CONFIDENTIALITY_REQUIREMENT", @cr),
|
128
|
+
get_key("INTEGRITY_REQUIREMENT", @ir),
|
129
|
+
get_key("AVAILABILITY_REQUIREMENT", @ar)]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def av=(av)
|
134
|
+
@av = case av
|
135
|
+
when "local", "L" then ACCESS_VECTOR[:local]
|
136
|
+
when "adjacent network", "A" then ACCESS_VECTOR[:adjacent_network]
|
137
|
+
when "network", "N" then ACCESS_VECTOR[:network]
|
138
|
+
else
|
139
|
+
raise "Bad Argument"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def av
|
144
|
+
av = get_key("ACCESS_VECTOR", @av) if !@av.nil?
|
145
|
+
end
|
146
|
+
|
147
|
+
def ac=(ac)
|
148
|
+
@ac = case ac
|
149
|
+
when "high", "H" then ACCESS_COMPLEXITY[:high]
|
150
|
+
when "medium", "M" then ACCESS_COMPLEXITY[:medium]
|
151
|
+
when "low", "L" then ACCESS_COMPLEXITY[:low]
|
152
|
+
else
|
153
|
+
raise "Bad Argument"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def ac
|
158
|
+
ac = get_key("ACCESS_COMPLEXITY", @ac) if !@ac.nil?
|
159
|
+
end
|
160
|
+
|
161
|
+
def au=(au)
|
162
|
+
@au = case au
|
163
|
+
when "none", "N" then AUTHENTICATION[:none]
|
164
|
+
when "single instance", "S" then AUTHENTICATION[:single]
|
165
|
+
when "multiple instance", "M" then AUTHENTICATION[:multiple]
|
166
|
+
else
|
167
|
+
raise "Bad Argument"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def au
|
172
|
+
au = get_key("AUTHENTICATION", @au) if !@au.nil?
|
173
|
+
end
|
174
|
+
|
175
|
+
def ci=(ci)
|
176
|
+
@ci = case ci
|
177
|
+
when "none", "N" then CONFIDENTIALITY_IMPACT[:none]
|
178
|
+
when "partial", "P" then CONFIDENTIALITY_IMPACT[:partial]
|
179
|
+
when "complete", "C" then CONFIDENTIALITY_IMPACT[:complete]
|
180
|
+
else
|
181
|
+
raise "Bad Argument"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def ci
|
186
|
+
ci = get_key("CONFIDENTIALITY_IMPACT", @ci) if !@ci.nil?
|
187
|
+
end
|
188
|
+
|
189
|
+
def ii=(ii)
|
190
|
+
@ii = case ii
|
191
|
+
when "none", "N" then INTEGRITY_IMPACT[:none]
|
192
|
+
when "partial", "P" then INTEGRITY_IMPACT[:partial]
|
193
|
+
when "complete", "C" then INTEGRITY_IMPACT[:complete]
|
194
|
+
else
|
195
|
+
raise "Bad Argument"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def ii
|
200
|
+
ii = get_key("INTEGRITY_IMPACT", @ii) if !@ii.nil?
|
201
|
+
end
|
202
|
+
|
203
|
+
def ai=(ai)
|
204
|
+
@ai = case ai
|
205
|
+
when "none", "N" then AVAILABILITY_IMPACT[:none]
|
206
|
+
when "partial", "P" then AVAILABILITY_IMPACT[:partial]
|
207
|
+
when "complete", "C" then AVAILABILITY_IMPACT[:complete]
|
208
|
+
else
|
209
|
+
raise "Bad Argument"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def ai
|
214
|
+
ai = get_key("AVAILABILITY_IMPACT", @ai) if !@ai.nil?
|
215
|
+
end
|
216
|
+
|
217
|
+
def ex=(ex)
|
218
|
+
@ex = case ex
|
219
|
+
when "unproven", "U" then EXPLOITABILITY[:unproven]
|
220
|
+
when "proof-of-concept", "P", "POC" then EXPLOITABILITY[:poc]
|
221
|
+
when "functional", "F" then EXPLOITABILITY[:functional]
|
222
|
+
when "high", "H" then EXPLOITABILITY[:high]
|
223
|
+
when "not defined", "ND" then EXPLOITABILITY[:notdefined]
|
224
|
+
else
|
225
|
+
raise "Bad Argument"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def ex
|
230
|
+
ex = get_key("EXPLOITABILITY", @ex) if !@ex.nil?
|
231
|
+
end
|
232
|
+
|
233
|
+
def rl=(rl)
|
234
|
+
@rl = case rl
|
235
|
+
when "official-fix", "O" then REMEDIATION_LEVEL[:official]
|
236
|
+
when "temporary-fix", "T", "TF" then REMEDIATION_LEVEL[:temporary]
|
237
|
+
when "workaround", "W" then REMEDIATION_LEVEL[:workaround]
|
238
|
+
when "unavailable", "U" then REMEDIATION_LEVEL[:unavailable]
|
239
|
+
when "not defined", "ND" then REMEDIATION_LEVEL[:notdefined]
|
240
|
+
else
|
241
|
+
raise "Bad Argument"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def rl
|
246
|
+
rl = get_key("REMEDIATION_LEVEL", @rl) if !@rl.nil?
|
247
|
+
end
|
248
|
+
|
249
|
+
def rc=(rc)
|
250
|
+
@rc = case rc
|
251
|
+
when "unconfirmed", "UC" then REPORT_CONFIDENCE[:unconfirmed]
|
252
|
+
when "uncorroborated", "UR" then REPORT_CONFIDENCE[:uncorroborated]
|
253
|
+
when "confirmed", "C" then REPORT_CONFIDENCE[:confirmed]
|
254
|
+
when "not defined", "ND" then REPORT_CONFIDENCE[:notdefined]
|
255
|
+
else
|
256
|
+
raise "Bad Argument"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def rc
|
261
|
+
rc = get_key("REPORT_CONFIDENCE", @rc) if !@av.nil?
|
262
|
+
end
|
263
|
+
|
264
|
+
def cdp=(cd)
|
265
|
+
@cdp = case cd
|
266
|
+
when "none", "N" then COLLATERAL_DAMAGE[:none]
|
267
|
+
when "low", "L" then COLLATERAL_DAMAGE[:low]
|
268
|
+
when "low-medium", "LM" then COLLATERAL_DAMAGE[:low_medium]
|
269
|
+
when "medium-high", "MH" then COLLATERAL_DAMAGE[:medium_high]
|
270
|
+
when "high", "H" then COLLATERAL_DAMAGE[:high]
|
271
|
+
when "not defined", "ND" then COLLATERAL_DAMAGE[:notdefined]
|
272
|
+
else
|
273
|
+
raise "Bad Argument"
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def cdp
|
278
|
+
cdp = get_key("COLLATERAL_DAMAGE", @cdp) if !@cdp.nil?
|
279
|
+
end
|
280
|
+
|
281
|
+
def td=(td)
|
282
|
+
@td = case td
|
283
|
+
when "none", "N" then TARGET_DISTRIBUTION[:none]
|
284
|
+
when "low", "L" then TARGET_DISTRIBUTION[:low]
|
285
|
+
when "medium", "M" then TARGET_DISTRIBUTION[:medium]
|
286
|
+
when "high", "H" then TARGET_DISTRIBUTION[:high]
|
287
|
+
when "not defined", "ND" then TARGET_DISTRIBUTION[:notdefined]
|
288
|
+
else
|
289
|
+
raise "Bad Argument"
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def td
|
294
|
+
td = get_key("TARGET_DISTRIBUTION", @td) if !@td.nil?
|
295
|
+
end
|
296
|
+
|
297
|
+
def cr=(cr)
|
298
|
+
@cr = case cr
|
299
|
+
when "low", "L" then CONFIDENTIALITY_REQUIREMENT[:low]
|
300
|
+
when "medium", "M" then CONFIDENTIALITY_REQUIREMENT[:medium]
|
301
|
+
when "high", "H" then CONFIDENTIALITY_REQUIREMENT[:high]
|
302
|
+
when "not defined", "ND" then CONFIDENTIALITY_REQUIREMENT[:notdefined]
|
303
|
+
else
|
304
|
+
raise "Bad Argument"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def cr
|
309
|
+
cr = get_key("CONFIDENTIALITY_REQUIREMENT", @cr) if !@cr.nil?
|
310
|
+
end
|
311
|
+
|
312
|
+
def ir=(ir)
|
313
|
+
@ir = case ir
|
314
|
+
when "low", "L" then INTEGRITY_REQUIREMENT[:low]
|
315
|
+
when "medium", "M" then INTEGRITY_REQUIREMENT[:medium]
|
316
|
+
when "high", "H" then INTEGRITY_REQUIREMENT[:high]
|
317
|
+
when "not defined", "ND" then INTEGRITY_REQUIREMENT[:notdefined]
|
318
|
+
else
|
319
|
+
raise "Bad Argument"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def ir
|
324
|
+
ir = get_key("INTEGRITY_REQUIREMENT", @ir) if !@ir.nil?
|
325
|
+
end
|
326
|
+
|
327
|
+
def ar=(ar)
|
328
|
+
@ar = case ar
|
329
|
+
when "low", "L" then AVAILABILITY_REQUIREMENT[:low]
|
330
|
+
when "medium", "M" then AVAILABILITY_REQUIREMENT[:medium]
|
331
|
+
when "high", "H" then AVAILABILITY_REQUIREMENT[:high]
|
332
|
+
when "not defined", "ND" then AVAILABILITY_REQUIREMENT[:notdefined]
|
333
|
+
else
|
334
|
+
raise "Bad Argument"
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def ar
|
339
|
+
ar = get_key("AVAILABILITY_REQUIREMENT", @ar) if !@ar.nil?
|
340
|
+
end
|
341
|
+
|
342
|
+
VECTORS = {
|
343
|
+
"av" => "av=",
|
344
|
+
"ac" => "ac=",
|
345
|
+
"au" => "au=",
|
346
|
+
"c" => "ci=",
|
347
|
+
"i" => "ii=",
|
348
|
+
"a" => "ai=",
|
349
|
+
"e" => "ex=",
|
350
|
+
"rl" => "rl=",
|
351
|
+
"rc" => "rc=",
|
352
|
+
"cdp" => "cdp=",
|
353
|
+
"td" => "td=",
|
354
|
+
"cr" => "cr=",
|
355
|
+
"ir" => "ir=",
|
356
|
+
"ar" => "ar="
|
357
|
+
}
|
358
|
+
|
359
|
+
def parse(vector)
|
360
|
+
string = vector.split("/")
|
361
|
+
len = string.length
|
362
|
+
|
363
|
+
self.init
|
364
|
+
|
365
|
+
@originalkey = vector
|
366
|
+
|
367
|
+
string.each do |section|
|
368
|
+
tmp = section.split(":")
|
369
|
+
send(VECTORS[tmp[0].downcase].to_sym, tmp[1])
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
def key
|
374
|
+
self.set_key
|
375
|
+
return @key
|
376
|
+
end
|
377
|
+
|
378
|
+
def to_s
|
379
|
+
printf "Base Score:\t\t\t%3.1f\n", @base
|
380
|
+
printf " Impact Subscore:\t\t%3.1f\n", @impact
|
381
|
+
printf " Exploitability Subscore:\t%3.1f\n", @exploitability
|
382
|
+
printf "Temporal Score:\t\t\t%3.1f\n", @temporal if !self.notemporal
|
383
|
+
printf "Environmental Score:\t\t%3.1f\n", @environmental if !self.noenvironmental
|
384
|
+
printf " Adjusted Impact Score:\t%3.1f\n", @adjimpact if !self.noenvironmental
|
385
|
+
printf "Overall Score:\t\t\t%3.1f\n", overallscore
|
386
|
+
end
|
387
|
+
|
388
|
+
def calculate
|
389
|
+
@impact = self.impactscore
|
390
|
+
@adjimpact = self.adjustedimpactscore
|
391
|
+
@exploitability = self.exploitabilityscore
|
392
|
+
@base = self.basescore
|
393
|
+
@temporal = self.temporalscore
|
394
|
+
@environmental = self.environmentalscore(self.adjustedtemporalscore(self.adjustedbasescore(@adjimpact, @exploitability)))
|
395
|
+
end
|
396
|
+
|
397
|
+
def adjustedimpactscore
|
398
|
+
tmp = []
|
399
|
+
tmp[0] = 10
|
400
|
+
tmp[1] = 10.41*(1-(1-@ci.abs*@cr.abs)*(1-@ii.abs*@ir.abs)*(1-@ai.abs*@ar.abs))
|
401
|
+
adjustedimpactscore = tmp.min
|
402
|
+
end
|
403
|
+
|
404
|
+
def adjustedbasescore(adjustedimpact, exploitabilityscore)
|
405
|
+
adjustedbasescore = (0.6*adjustedimpact + 0.4 * exploitabilityscore - 1.5) * impactfunction(adjustedimpact)
|
406
|
+
end
|
407
|
+
|
408
|
+
def adjustedtemporalscore(adjustedbasescore)
|
409
|
+
adjustedtemporalscore = adjustedbasescore * @ex.abs * @rl.abs * @rc.abs
|
410
|
+
end
|
411
|
+
|
412
|
+
def exploitabilityscore
|
413
|
+
exploitability = 20 * @ac.abs * @au.abs * @av.abs
|
414
|
+
end
|
415
|
+
|
416
|
+
def environmentalscore(adjustedtemporalscore)
|
417
|
+
environmentalscore = (adjustedtemporalscore + (10 - adjustedtemporalscore) * (@cdp == -1 ? 0 : @cdp.abs)) * @td.abs
|
418
|
+
|
419
|
+
return environmentalscore == 0.0 ? "Undefined" : environmentalscore
|
420
|
+
end
|
421
|
+
|
422
|
+
def overallscore
|
423
|
+
if self.noenvironmental
|
424
|
+
if self.notemporal
|
425
|
+
overallscore = @base
|
426
|
+
else
|
427
|
+
overallscore = @temporal
|
428
|
+
end
|
429
|
+
else
|
430
|
+
overallscore = @environmental
|
431
|
+
end
|
432
|
+
return overallscore
|
433
|
+
end
|
434
|
+
|
435
|
+
def impactfunction(impact)
|
436
|
+
return impact != 0 ? 1.176 : 0.0
|
437
|
+
end
|
438
|
+
|
439
|
+
def impactscore
|
440
|
+
impact = 10.41*(1.0-(1.0-@ci.abs)*(1.0-@ii.abs)*(1.0-@ai.abs))
|
441
|
+
end
|
442
|
+
|
443
|
+
def basescore
|
444
|
+
basescore = (0.6 * @impact + 0.4 * @exploitability - 1.5) * impactfunction(@impact)
|
445
|
+
end
|
446
|
+
|
447
|
+
def temporalscore
|
448
|
+
temporalscore = @base * @ex.abs * @rl.abs * @rc.abs
|
449
|
+
|
450
|
+
return temporalscore == 0.0 ? "Undefined" : temporalscore
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'active_support'
|
3
|
+
require 'cvss_rating'
|
4
|
+
|
5
|
+
class CvssRatingTest < MiniTest::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@cvss = Cvss::Rating.new
|
8
|
+
@cvss.av = "N"
|
9
|
+
@cvss.ac = "M"
|
10
|
+
@cvss.au = "N"
|
11
|
+
@cvss.ci = "P"
|
12
|
+
@cvss.ii = "P"
|
13
|
+
@cvss.ai = "P"
|
14
|
+
@cvss.set_key
|
15
|
+
|
16
|
+
@cvss_2 = Cvss::Rating.new
|
17
|
+
@cvss_2.av = "L"
|
18
|
+
@cvss_2.ac = "M"
|
19
|
+
@cvss_2.au = "M"
|
20
|
+
@cvss_2.ci = "P"
|
21
|
+
@cvss_2.ii = "C"
|
22
|
+
@cvss_2.ai = "C"
|
23
|
+
@cvss_2.cdp = "L"
|
24
|
+
@cvss_2.td = "H"
|
25
|
+
@cvss_2.cr = "M"
|
26
|
+
@cvss_2.ir = "M"
|
27
|
+
@cvss_2.ar = "M"
|
28
|
+
@cvss_2.set_key
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_cvss_rating_from_vector
|
32
|
+
cvss = Cvss::Rating.new
|
33
|
+
cvss.parse("AV:N/AC:M/Au:N/C:P/I:P/A:P")
|
34
|
+
assert_equal @cvss.key, cvss.key
|
35
|
+
|
36
|
+
assert_equal @cvss.base, cvss.base
|
37
|
+
|
38
|
+
assert_equal @cvss.overallscore, cvss.overallscore
|
39
|
+
|
40
|
+
cvss.init
|
41
|
+
cvss.parse("AV:L/AC:M/Au:M/C:P/I:C/A:C/CDP:L/TD:H/CR:M/IR:M/AR:M")
|
42
|
+
assert_equal @cvss_2.key, cvss.key
|
43
|
+
|
44
|
+
assert_equal @cvss_2.base, cvss.base
|
45
|
+
|
46
|
+
assert_equal @cvss_2.overallscore, cvss.overallscore
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_cvss_rating_parameters
|
50
|
+
cvss = Cvss::Rating.new
|
51
|
+
cvss.init
|
52
|
+
|
53
|
+
cvss.av = "local"
|
54
|
+
|
55
|
+
assert_equal @cvss_2.av, cvss.av
|
56
|
+
|
57
|
+
cvss.cdp = 'low'
|
58
|
+
|
59
|
+
assert_equal @cvss_2.cdp, cvss.cdp
|
60
|
+
end
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cvss_rating
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Kapp
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: CVSS Risk Rating Calucation and Vector parsing, implements CVSS 2.0 rating
|
42
|
+
email:
|
43
|
+
- mort666@virus.org
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- cvss_rating.gemspec
|
54
|
+
- lib/cvss_rating.rb
|
55
|
+
- lib/cvss_rating/version.rb
|
56
|
+
- test/cvss_rating_test.rb
|
57
|
+
homepage: https://github.com/mort666/cvss_rating
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.2.2
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: CVSS Risk Rating Calucation and Vector parsing
|
81
|
+
test_files:
|
82
|
+
- test/cvss_rating_test.rb
|