dradis-calculator_cvss 3.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/issue_template.md +16 -0
- data/.github/pull_request_template.md +36 -0
- data/.gitignore +10 -0
- data/CHANGELOG.md +64 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +3 -0
- data/LICENSE +339 -0
- data/README.md +40 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/dradis/plugins/calculators/cvss/calculator.js.coffee +135 -0
- data/app/assets/javascripts/dradis/plugins/calculators/cvss/manifests/application.js +7 -0
- data/app/assets/javascripts/dradis/plugins/calculators/cvss/manifests/tylium.js +2 -0
- data/app/assets/javascripts/dradis/plugins/calculators/cvss/vendor/cvsscalc30.js +689 -0
- data/app/assets/stylesheets/dradis/plugins/calculators/cvss/manifests/application.css.scss +4 -0
- data/app/controllers/dradis/plugins/calculators/cvss/base_controller.rb +8 -0
- data/app/controllers/dradis/plugins/calculators/cvss/issues_controller.rb +37 -0
- data/app/models/dradis/plugins/calculators/cvss/v3.rb +38 -0
- data/app/views/dradis/plugins/calculators/cvss/_addons_menu.html.erb +1 -0
- data/app/views/dradis/plugins/calculators/cvss/_addons_menu_bs4.html.erb +1 -0
- data/app/views/dradis/plugins/calculators/cvss/base/_base.html.erb +123 -0
- data/app/views/dradis/plugins/calculators/cvss/base/_environmental.html.erb +192 -0
- data/app/views/dradis/plugins/calculators/cvss/base/_temporal.html.erb +67 -0
- data/app/views/dradis/plugins/calculators/cvss/base/index.html.erb +79 -0
- data/app/views/dradis/plugins/calculators/cvss/issues/_show-content.html.erb +20 -0
- data/app/views/dradis/plugins/calculators/cvss/issues/_show-tabs.html.erb +3 -0
- data/app/views/dradis/plugins/calculators/cvss/issues/edit.html.erb +103 -0
- data/app/views/layouts/dradis/plugins/calculators/cvss/base.html.erb +27 -0
- data/config/routes.rb +12 -0
- data/dradis-calculator_cvss.gemspec +27 -0
- data/lib/dradis-calculator_cvss.rb +13 -0
- data/lib/dradis/plugins/calculators/cvss/engine.rb +26 -0
- data/lib/dradis/plugins/calculators/cvss/gem_version.rb +21 -0
- data/lib/dradis/plugins/calculators/cvss/version.rb +15 -0
- metadata +118 -0
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# CVSS score calculator for Dradis
|
2
|
+
|
3
|
+
This simple add-on adds a new page under `/calculators/cvss` for you to perform CVSS score calculations:
|
4
|
+
|
5
|
+
![cvss_calculator](https://cloud.githubusercontent.com/assets/53006/12947493/f01cb53a-cffb-11e5-8f48-19072a3bd8c8.png)
|
6
|
+
|
7
|
+
The Common Vulnerability Scoring System Version 3.0 (CVSSv3) Calculator is heavily inspired in the one provided by [FIRST](https://www.first.org/cvss/calculator/3.0).
|
8
|
+
|
9
|
+
|
10
|
+
## Install
|
11
|
+
|
12
|
+
Add this to your `Gemfile.plugins`:
|
13
|
+
|
14
|
+
gem 'dradis-calculator_cvss'
|
15
|
+
|
16
|
+
And
|
17
|
+
|
18
|
+
bundle install
|
19
|
+
|
20
|
+
Restart your Dradis server and you should be good to go.
|
21
|
+
|
22
|
+
|
23
|
+
## More information
|
24
|
+
|
25
|
+
See the Dradis Framework's [README.md](https://github.com/dradis/dradisframework/blob/master/README.md)
|
26
|
+
|
27
|
+
|
28
|
+
## Contributing
|
29
|
+
|
30
|
+
See the Dradis Framework's [CONTRIBUTING.md](https://github.com/dradis/dradisframework/blob/master/CONTRIBUTING.md)
|
31
|
+
|
32
|
+
|
33
|
+
## License
|
34
|
+
|
35
|
+
Dradis Framework and all its components are released under [GNU General Public License version 2.0](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.
|
36
|
+
|
37
|
+
|
38
|
+
## Feature requests and bugs
|
39
|
+
|
40
|
+
Please use the [Dradis Framework issue tracker](https://github.com/dradis/dradis-ce/issues) for add-on improvements and bug reports.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,135 @@
|
|
1
|
+
@CVSSCalculator =
|
2
|
+
calculate: ->
|
3
|
+
av = $("input[name=av]").val()
|
4
|
+
ac = $("input[name=ac]").val()
|
5
|
+
pr = $("input[name=pr]").val()
|
6
|
+
ui = $("input[name=ui]").val()
|
7
|
+
s = $("input[name=s]").val()
|
8
|
+
c = $("input[name=c]").val()
|
9
|
+
i = $("input[name=i]").val()
|
10
|
+
a = $("input[name=a]").val()
|
11
|
+
|
12
|
+
e = $("input[name=e]").val()
|
13
|
+
rl = $("input[name=rl]").val()
|
14
|
+
rc = $("input[name=rc]").val()
|
15
|
+
|
16
|
+
cr = $("input[name=cr]").val()
|
17
|
+
ir = $("input[name=ir]").val()
|
18
|
+
ar = $("input[name=ar]").val()
|
19
|
+
mav = $("input[name=mav]").val()
|
20
|
+
mac = $("input[name=mac]").val()
|
21
|
+
mpr = $("input[name=mpr]").val()
|
22
|
+
mui = $("input[name=mui]").val()
|
23
|
+
ms = $("input[name=ms]").val()
|
24
|
+
mc = $("input[name=mc]").val()
|
25
|
+
mi = $("input[name=mi]").val()
|
26
|
+
ma = $("input[name=ma]").val()
|
27
|
+
|
28
|
+
# AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope,
|
29
|
+
# Confidentiality, Integrity, Availability, Exploitability, RemediationLevel,
|
30
|
+
# ReportConfidence, ConfidentialityRequirement, IntegrityRequirement,
|
31
|
+
# AvailabilityRequirement, ModifiedAttackVector, ModifiedAttackComplexity,
|
32
|
+
# ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
|
33
|
+
# ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability
|
34
|
+
output = CVSS.calculateCVSSFromMetrics(av, ac, pr, ui, s, c, i, a,
|
35
|
+
e, rl, rc,
|
36
|
+
cr, ir, ar, mav, mac, mpr, mui, ms, mc, mi, ma);
|
37
|
+
|
38
|
+
|
39
|
+
if output.success == true
|
40
|
+
$('input[type=submit]').attr('disabled', null)
|
41
|
+
$('[data-behavior~=cvss-error]').addClass('d-none').text('')
|
42
|
+
$('#base-score').text("#{output.baseMetricScore} (#{output.baseSeverity})")
|
43
|
+
$('#temporal-score').text("#{output.temporalMetricScore} (#{output.temporalSeverity})")
|
44
|
+
$('#environmental-score').text("#{output.environmentalMetricScore} (#{output.environmentalSeverity})")
|
45
|
+
|
46
|
+
issue_cvss = "#[CVSSv3.Vector]#\n"
|
47
|
+
issue_cvss += "#{output.vectorString}\n\n"
|
48
|
+
issue_cvss += "#[CVSSv3.BaseScore]#\n"
|
49
|
+
issue_cvss += "#{output.baseMetricScore}\n\n"
|
50
|
+
issue_cvss += "#[CVSSv3.BaseSeverity]#\n"
|
51
|
+
issue_cvss += "#{output.baseSeverity}\n\n"
|
52
|
+
issue_cvss += "#[CVSSv3.TemporalScore]#\n"
|
53
|
+
issue_cvss += "#{output.temporalMetricScore}\n\n"
|
54
|
+
issue_cvss += "#[CVSSv3.TemporalSeverity]#\n"
|
55
|
+
issue_cvss += "#{output.temporalSeverity}\n\n"
|
56
|
+
issue_cvss += "#[CVSSv3.EnvironmentalScore]#\n"
|
57
|
+
issue_cvss += "#{output.environmentalMetricScore}\n\n"
|
58
|
+
issue_cvss += "#[CVSSv3.EnvironmentalSeverity]#\n"
|
59
|
+
issue_cvss += "#{output.environmentalSeverity}\n\n"
|
60
|
+
|
61
|
+
# Base metrics
|
62
|
+
issue_cvss += "#[CVSSv3.BaseAttackVector]#\n"
|
63
|
+
issue_cvss += "#{$("button[name=av].btn-primary").data('label')}\n\n"
|
64
|
+
issue_cvss += "#[CVSSv3.BaseAttackComplexity]#\n"
|
65
|
+
issue_cvss += "#{$("button[name=ac].btn-primary").data('label')}\n\n"
|
66
|
+
issue_cvss += "#[CVSSv3.BasePrivilegesRequired]#\n"
|
67
|
+
issue_cvss += "#{$("button[name=pr].btn-primary").data('label')}\n\n"
|
68
|
+
issue_cvss += "#[CVSSv3.BaseUserInteraction]#\n"
|
69
|
+
issue_cvss += "#{$("button[name=ui].btn-primary").data('label')}\n\n"
|
70
|
+
issue_cvss += "#[CVSSv3.BaseScope]#\n"
|
71
|
+
issue_cvss += "#{$("button[name=s].btn-primary").data('label')}\n\n"
|
72
|
+
issue_cvss += "#[CVSSv3.BaseConfidentiality]#\n"
|
73
|
+
issue_cvss += "#{$("button[name=c].btn-primary").data('label')}\n\n"
|
74
|
+
issue_cvss += "#[CVSSv3.BaseIntegrity]#\n"
|
75
|
+
issue_cvss += "#{$("button[name=i].btn-primary").data('label')}\n\n"
|
76
|
+
issue_cvss += "#[CVSSv3.BaseAvailability]#\n"
|
77
|
+
issue_cvss += "#{$("button[name=a].btn-primary").data('label')}\n\n"
|
78
|
+
|
79
|
+
# Temporal metrics
|
80
|
+
issue_cvss += "#[CVSSv3.TemporalExploitCodeMaturity]#\n"
|
81
|
+
issue_cvss += "#{$("button[name=e].btn-primary").data('label')}\n\n"
|
82
|
+
issue_cvss += "#[CVSSv3.TemporalRemediationLevel]#\n"
|
83
|
+
issue_cvss += "#{$("button[name=rl].btn-primary").data('label')}\n\n"
|
84
|
+
issue_cvss += "#[CVSSv3.TemporalReportConfidence]#\n"
|
85
|
+
issue_cvss += "#{$("button[name=rc].btn-primary").data('label')}\n\n"
|
86
|
+
|
87
|
+
# Environmental metrics
|
88
|
+
issue_cvss += "#[CVSSv3.EnvironmentalConfidentialityRequirement]#\n"
|
89
|
+
issue_cvss += "#{$("button[name=cr].btn-primary").data('label')}\n\n"
|
90
|
+
issue_cvss += "#[CVSSv3.EnvironmentalIntegrityRequirement]#\n"
|
91
|
+
issue_cvss += "#{$("button[name=ir].btn-primary").data('label')}\n\n"
|
92
|
+
issue_cvss += "#[CVSSv3.EnvironmentalAvailabilityRequirement]#\n"
|
93
|
+
issue_cvss += "#{$("button[name=ar].btn-primary").data('label')}\n\n"
|
94
|
+
|
95
|
+
issue_cvss += "#[CVSSv3.ModifiedAttackVector]#\n"
|
96
|
+
issue_cvss += "#{$("button[name=mav].btn-primary").data('label')}\n\n"
|
97
|
+
issue_cvss += "#[CVSSv3.ModifiedAttackComplexity]#\n"
|
98
|
+
issue_cvss += "#{$("button[name=mac].btn-primary").data('label')}\n\n"
|
99
|
+
issue_cvss += "#[CVSSv3.ModifiedPrivilegesRequired]#\n"
|
100
|
+
issue_cvss += "#{$("button[name=mpr].btn-primary").data('label')}\n\n"
|
101
|
+
issue_cvss += "#[CVSSv3.ModifiedUserInteraction]#\n"
|
102
|
+
issue_cvss += "#{$("button[name=mui].btn-primary").data('label')}\n\n"
|
103
|
+
issue_cvss += "#[CVSSv3.ModifiedScope]#\n"
|
104
|
+
issue_cvss += "#{$("button[name=ms].btn-primary").data('label')}\n\n"
|
105
|
+
issue_cvss += "#[CVSSv3.ModifiedConfidentiality]#\n"
|
106
|
+
issue_cvss += "#{$("button[name=mc].btn-primary").data('label')}\n\n"
|
107
|
+
issue_cvss += "#[CVSSv3.ModifiedIntegrity]#\n"
|
108
|
+
issue_cvss += "#{$("button[name=mi].btn-primary").data('label')}\n\n"
|
109
|
+
issue_cvss += "#[CVSSv3.ModifiedAvailability]#\n"
|
110
|
+
issue_cvss += "#{$("button[name=ma].btn-primary").data('label')}\n\n"
|
111
|
+
|
112
|
+
$('textarea[name=cvss_fields]').val(issue_cvss)
|
113
|
+
else
|
114
|
+
errorMessage = ''
|
115
|
+
|
116
|
+
if output.errorType == 'MissingBaseMetric'
|
117
|
+
errorMessage = "The error type is '#{output.errorType}' and the metrics with errors are #{output.errorMetrics}."
|
118
|
+
else
|
119
|
+
errorMessage = "All Base metrics are required"
|
120
|
+
|
121
|
+
$('input[type=submit]').attr('disabled', 'disabled')
|
122
|
+
$('[data-behavior~=cvss-error]').removeClass('d-none').text(errorMessage)
|
123
|
+
|
124
|
+
document.addEventListener "turbolinks:load", ->
|
125
|
+
if $('[data-behavior~=cvss-buttons]').length
|
126
|
+
CVSSCalculator.calculate()
|
127
|
+
$('[data-behavior~=cvss-error]').addClass('d-none')
|
128
|
+
|
129
|
+
$('[data-behavior~=cvss-buttons] button').on 'click', ->
|
130
|
+
|
131
|
+
$this = $(this)
|
132
|
+
$this.parent().find('button').removeClass('active btn-primary');
|
133
|
+
$this.addClass('active btn-primary');
|
134
|
+
$("input[name=#{$this.attr('name')}]").val($this.val())
|
135
|
+
CVSSCalculator.calculate()
|
@@ -0,0 +1,689 @@
|
|
1
|
+
/* Copyright (c) 2015, FIRST.ORG, INC.
|
2
|
+
* All rights reserved.
|
3
|
+
*
|
4
|
+
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
5
|
+
* following conditions are met:
|
6
|
+
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
7
|
+
* disclaimer.
|
8
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
9
|
+
* following disclaimer in the documentation and/or other materials provided with the distribution.
|
10
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
11
|
+
* products derived from this software without specific prior written permission.
|
12
|
+
*
|
13
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
14
|
+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
15
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
16
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
17
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
18
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
19
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
20
|
+
*/
|
21
|
+
|
22
|
+
/* This JavaScript contains two main functions. Both take CVSS metric values and calculate CVSS scores for Base,
|
23
|
+
* Temporal and Environmental metric groups, their associated severity ratings, and an overall Vector String.
|
24
|
+
*
|
25
|
+
* Use CVSS.calculateCVSSFromMetrics if you wish to pass metric values as individual parameters.
|
26
|
+
* Use CVSS.calculateCVSSFromVector if you wish to pass metric values as a single Vector String.
|
27
|
+
*
|
28
|
+
* Changelog
|
29
|
+
*
|
30
|
+
* 2018-02-15 Darius Wiles Added a missing pair of parantheses in the Environmental score, specifically
|
31
|
+
* in the code setting envScore in the main clause (not the else clause). It was changed
|
32
|
+
* from "min (...), 10" to "min ((...), 10)". This correction does not alter any final
|
33
|
+
* Environmental scores.
|
34
|
+
*
|
35
|
+
* 2015-08-04 Darius Wiles Added CVSS.generateXMLFromMetrics and CVSS.generateXMLFromVector functions to return
|
36
|
+
* XML string representations of: a set of metric values; or a Vector String respectively.
|
37
|
+
* Moved all constants and functions to an object named "CVSS" to
|
38
|
+
* reduce the chance of conflicts in global variables when this file is combined with
|
39
|
+
* other JavaScript code. This will break all existing code that uses this file until
|
40
|
+
* the string "CVSS." is prepended to all references. The "Exploitability" metric has been
|
41
|
+
* renamed "Exploit Code Maturity" in the specification, so the same change has been made
|
42
|
+
* in the code in this file.
|
43
|
+
*
|
44
|
+
* 2015-04-24 Darius Wiles Environmental formula modified to eliminate undesirable behavior caused by subtle
|
45
|
+
* differences in rounding between Temporal and Environmental formulas that often
|
46
|
+
* caused the latter to be 0.1 lower than than the former when all Environmental
|
47
|
+
* metrics are "Not defined". Also added a RoundUp1 function to simplify formulas.
|
48
|
+
*
|
49
|
+
* 2015-04-09 Darius Wiles Added calculateCVSSFromVector function, license information, cleaned up code and improved
|
50
|
+
* comments.
|
51
|
+
*
|
52
|
+
* 2014-12-12 Darius Wiles Initial release for CVSS 3.0 Preview 2.
|
53
|
+
*/
|
54
|
+
|
55
|
+
// Constants used in the formula. They are not declared as "const" to avoid problems in older browsers.
|
56
|
+
|
57
|
+
var CVSS = {};
|
58
|
+
|
59
|
+
CVSS.CVSSVersionIdentifier = "CVSS:3.0";
|
60
|
+
CVSS.exploitabilityCoefficient = 8.22;
|
61
|
+
CVSS.scopeCoefficient = 1.08;
|
62
|
+
|
63
|
+
// A regular expression to validate that a CVSS 3.0 vector string is well formed. It checks metrics and metric
|
64
|
+
// values. It does not check that a metric is specified more than once and it does not check that all base
|
65
|
+
// metrics are present. These checks need to be performed separately.
|
66
|
+
|
67
|
+
CVSS.vectorStringRegex_30 = /^CVSS:3\.0\/((AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])\/)*(AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$/;
|
68
|
+
|
69
|
+
|
70
|
+
// Associative arrays mapping each metric value to the constant defined in the CVSS scoring formula in the CVSS v3.0
|
71
|
+
// specification.
|
72
|
+
|
73
|
+
CVSS.Weight = {
|
74
|
+
AV: { N: 0.85, A: 0.62, L: 0.55, P: 0.2},
|
75
|
+
AC: { H: 0.44, L: 0.77},
|
76
|
+
PR: { U: {N: 0.85, L: 0.62, H: 0.27}, // These values are used if Scope is Unchanged
|
77
|
+
C: {N: 0.85, L: 0.68, H: 0.5}}, // These values are used if Scope is Changed
|
78
|
+
UI: { N: 0.85, R: 0.62},
|
79
|
+
S: { U: 6.42, C: 7.52}, // Note: not defined as constants in specification
|
80
|
+
CIA: { N: 0, L: 0.22, H: 0.56}, // C, I and A have the same weights
|
81
|
+
|
82
|
+
E: { X: 1, U: 0.91, P: 0.94, F: 0.97, H: 1},
|
83
|
+
RL: { X: 1, O: 0.95, T: 0.96, W: 0.97, U: 1},
|
84
|
+
RC: { X: 1, U: 0.92, R: 0.96, C: 1},
|
85
|
+
|
86
|
+
CIAR: { X: 1, L: 0.5, M: 1, H: 1.5} // CR, IR and AR have the same weights
|
87
|
+
};
|
88
|
+
|
89
|
+
|
90
|
+
// Severity rating bands, as defined in the CVSS v3.0 specification.
|
91
|
+
|
92
|
+
CVSS.severityRatings = [ { name: "None", bottom: 0.0, top: 0.0},
|
93
|
+
{ name: "Low", bottom: 0.1, top: 3.9},
|
94
|
+
{ name: "Medium", bottom: 4.0, top: 6.9},
|
95
|
+
{ name: "High", bottom: 7.0, top: 8.9},
|
96
|
+
{ name: "Critical", bottom: 9.0, top: 10.0} ];
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
/* ** CVSS.calculateCVSSFromMetrics **
|
102
|
+
*
|
103
|
+
* Takes Base, Temporal and Environmental metric values as individual parameters. Their values are in the short format
|
104
|
+
* defined in the CVSS v3.0 standard definition of the Vector String. For example, the AttackComplexity parameter
|
105
|
+
* should be either "H" or "L".
|
106
|
+
*
|
107
|
+
* Returns Base, Temporal and Environmental scores, severity ratings, and an overall Vector String. All Base metrics
|
108
|
+
* are required to generate this output. All Temporal and Environmental metric values are optional. Any that are not
|
109
|
+
* passed default to "X" ("Not Defined").
|
110
|
+
*
|
111
|
+
* The output is an object which always has a property named "success".
|
112
|
+
*
|
113
|
+
* If no errors are encountered, success is Boolean "true", and the following other properties are defined containing
|
114
|
+
* scores, severities and a vector string:
|
115
|
+
* baseMetricScore, baseSeverity,
|
116
|
+
* temporalMetricScore, temporalSeverity,
|
117
|
+
* environmentalMetricScore, environmentalSeverity,
|
118
|
+
* vectorString
|
119
|
+
*
|
120
|
+
* If errors are encountered, success is Boolean "false", and the following other properties are defined:
|
121
|
+
* errorType - a string indicating the error. Either:
|
122
|
+
* "MissingBaseMetric", if at least one Base metric has not been defined; or
|
123
|
+
* "UnknownMetricValue", if at least one metric value is invalid.
|
124
|
+
* errorMetrics - an array of strings representing the metrics at fault. The strings are abbreviated versions of the
|
125
|
+
* metrics, as defined in the CVSS v3.0 standard definition of the Vector String.
|
126
|
+
*/
|
127
|
+
CVSS.calculateCVSSFromMetrics = function (
|
128
|
+
AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope, Confidentiality, Integrity, Availability,
|
129
|
+
ExploitCodeMaturity, RemediationLevel, ReportConfidence,
|
130
|
+
ConfidentialityRequirement, IntegrityRequirement, AvailabilityRequirement,
|
131
|
+
ModifiedAttackVector, ModifiedAttackComplexity, ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
|
132
|
+
ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability) {
|
133
|
+
|
134
|
+
// If input validation fails, this array is populated with strings indicating which metrics failed validation.
|
135
|
+
var badMetrics = [];
|
136
|
+
|
137
|
+
// ENSURE ALL BASE METRICS ARE DEFINED
|
138
|
+
//
|
139
|
+
// We need values for all Base Score metrics to calculate scores.
|
140
|
+
// If any Base Score parameters are undefined, create an array of missing metrics and return it with an error.
|
141
|
+
|
142
|
+
if (typeof AttackVector === "undefined" || AttackVector === "") { badMetrics.push("AV"); }
|
143
|
+
if (typeof AttackComplexity === "undefined" || AttackComplexity === "") { badMetrics.push("AC"); }
|
144
|
+
if (typeof PrivilegesRequired === "undefined" || PrivilegesRequired === "") { badMetrics.push("PR"); }
|
145
|
+
if (typeof UserInteraction === "undefined" || UserInteraction === "") { badMetrics.push("UI"); }
|
146
|
+
if (typeof Scope === "undefined" || Scope === "") { badMetrics.push("S"); }
|
147
|
+
if (typeof Confidentiality === "undefined" || Confidentiality === "") { badMetrics.push("C"); }
|
148
|
+
if (typeof Integrity === "undefined" || Integrity === "") { badMetrics.push("I"); }
|
149
|
+
if (typeof Availability === "undefined" || Availability === "") { badMetrics.push("A"); }
|
150
|
+
|
151
|
+
if (badMetrics.length > 0) {
|
152
|
+
return { success: false, errorType: "MissingBaseMetric", errorMetrics: badMetrics };
|
153
|
+
}
|
154
|
+
|
155
|
+
|
156
|
+
// STORE THE METRIC VALUES THAT WERE PASSED AS PARAMETERS
|
157
|
+
//
|
158
|
+
// Temporal and Environmental metrics are optional, so set them to "X" ("Not Defined") if no value was passed.
|
159
|
+
|
160
|
+
var AV = AttackVector;
|
161
|
+
var AC = AttackComplexity;
|
162
|
+
var PR = PrivilegesRequired;
|
163
|
+
var UI = UserInteraction;
|
164
|
+
var S = Scope;
|
165
|
+
var C = Confidentiality;
|
166
|
+
var I = Integrity;
|
167
|
+
var A = Availability;
|
168
|
+
|
169
|
+
var E = ExploitCodeMaturity || "X";
|
170
|
+
var RL = RemediationLevel || "X";
|
171
|
+
var RC = ReportConfidence || "X";
|
172
|
+
|
173
|
+
var CR = ConfidentialityRequirement || "X";
|
174
|
+
var IR = IntegrityRequirement || "X";
|
175
|
+
var AR = AvailabilityRequirement || "X";
|
176
|
+
var MAV = ModifiedAttackVector || "X";
|
177
|
+
var MAC = ModifiedAttackComplexity || "X";
|
178
|
+
var MPR = ModifiedPrivilegesRequired || "X";
|
179
|
+
var MUI = ModifiedUserInteraction || "X";
|
180
|
+
var MS = ModifiedScope || "X";
|
181
|
+
var MC = ModifiedConfidentiality || "X";
|
182
|
+
var MI = ModifiedIntegrity || "X";
|
183
|
+
var MA = ModifiedAvailability || "X";
|
184
|
+
|
185
|
+
|
186
|
+
// CHECK VALIDITY OF METRIC VALUES
|
187
|
+
//
|
188
|
+
// Use the Weight object to ensure that, for every metric, the metric value passed is valid.
|
189
|
+
// If any invalid values are found, create an array of their metrics and return it with an error.
|
190
|
+
//
|
191
|
+
// The Privileges Required (PR) weight depends on Scope, but when checking the validity of PR we must not assume
|
192
|
+
// that the given value for Scope is valid. We therefore always look at the weights for Unchanged Scope when
|
193
|
+
// performing this check. The same applies for validation of Modified Privileges Required (MPR).
|
194
|
+
//
|
195
|
+
// The Weights object does not contain "X" ("Not Defined") values for Environmental metrics because we replace them
|
196
|
+
// with their Base metric equivalents later in the function. For example, an MAV of "X" will be replaced with the
|
197
|
+
// value given for AV. We therefore need to explicitly allow a value of "X" for Environmental metrics.
|
198
|
+
|
199
|
+
if (!CVSS.Weight.AV.hasOwnProperty(AV)) { badMetrics.push("AV"); }
|
200
|
+
if (!CVSS.Weight.AC.hasOwnProperty(AC)) { badMetrics.push("AC"); }
|
201
|
+
if (!CVSS.Weight.PR.U.hasOwnProperty(PR)) { badMetrics.push("PR"); }
|
202
|
+
if (!CVSS.Weight.UI.hasOwnProperty(UI)) { badMetrics.push("UI"); }
|
203
|
+
if (!CVSS.Weight.S.hasOwnProperty(S)) { badMetrics.push("S"); }
|
204
|
+
if (!CVSS.Weight.CIA.hasOwnProperty(C)) { badMetrics.push("C"); }
|
205
|
+
if (!CVSS.Weight.CIA.hasOwnProperty(I)) { badMetrics.push("I"); }
|
206
|
+
if (!CVSS.Weight.CIA.hasOwnProperty(A)) { badMetrics.push("A"); }
|
207
|
+
|
208
|
+
if (!CVSS.Weight.E.hasOwnProperty(E)) { badMetrics.push("E"); }
|
209
|
+
if (!CVSS.Weight.RL.hasOwnProperty(RL)) { badMetrics.push("RL"); }
|
210
|
+
if (!CVSS.Weight.RC.hasOwnProperty(RC)) { badMetrics.push("RC"); }
|
211
|
+
|
212
|
+
if (!(CR === "X" || CVSS.Weight.CIAR.hasOwnProperty(CR))) { badMetrics.push("CR"); }
|
213
|
+
if (!(IR === "X" || CVSS.Weight.CIAR.hasOwnProperty(IR))) { badMetrics.push("IR"); }
|
214
|
+
if (!(AR === "X" || CVSS.Weight.CIAR.hasOwnProperty(AR))) { badMetrics.push("AR"); }
|
215
|
+
if (!(MAV === "X" || CVSS.Weight.AV.hasOwnProperty(MAV))) { badMetrics.push("MAV"); }
|
216
|
+
if (!(MAC === "X" || CVSS.Weight.AC.hasOwnProperty(MAC))) { badMetrics.push("MAC"); }
|
217
|
+
if (!(MPR === "X" || CVSS.Weight.PR.U.hasOwnProperty(MPR))) { badMetrics.push("MPR"); }
|
218
|
+
if (!(MUI === "X" || CVSS.Weight.UI.hasOwnProperty(MUI))) { badMetrics.push("MUI"); }
|
219
|
+
if (!(MS === "X" || CVSS.Weight.S.hasOwnProperty(MS))) { badMetrics.push("MS"); }
|
220
|
+
if (!(MC === "X" || CVSS.Weight.CIA.hasOwnProperty(MC))) { badMetrics.push("MC"); }
|
221
|
+
if (!(MI === "X" || CVSS.Weight.CIA.hasOwnProperty(MI))) { badMetrics.push("MI"); }
|
222
|
+
if (!(MA === "X" || CVSS.Weight.CIA.hasOwnProperty(MA))) { badMetrics.push("MA"); }
|
223
|
+
|
224
|
+
if (badMetrics.length > 0) {
|
225
|
+
return { success: false, errorType: "UnknownMetricValue", errorMetrics: badMetrics };
|
226
|
+
}
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
// GATHER WEIGHTS FOR ALL METRICS
|
231
|
+
|
232
|
+
var metricWeightAV = CVSS.Weight.AV [AV];
|
233
|
+
var metricWeightAC = CVSS.Weight.AC [AC];
|
234
|
+
var metricWeightPR = CVSS.Weight.PR [S][PR]; // PR depends on the value of Scope (S).
|
235
|
+
var metricWeightUI = CVSS.Weight.UI [UI];
|
236
|
+
var metricWeightS = CVSS.Weight.S [S];
|
237
|
+
var metricWeightC = CVSS.Weight.CIA [C];
|
238
|
+
var metricWeightI = CVSS.Weight.CIA [I];
|
239
|
+
var metricWeightA = CVSS.Weight.CIA [A];
|
240
|
+
|
241
|
+
var metricWeightE = CVSS.Weight.E [E];
|
242
|
+
var metricWeightRL = CVSS.Weight.RL [RL];
|
243
|
+
var metricWeightRC = CVSS.Weight.RC [RC];
|
244
|
+
|
245
|
+
// For metrics that are modified versions of Base Score metrics, e.g. Modified Attack Vector, use the value of
|
246
|
+
// the Base Score metric if the modified version value is "X" ("Not Defined").
|
247
|
+
var metricWeightCR = CVSS.Weight.CIAR [CR];
|
248
|
+
var metricWeightIR = CVSS.Weight.CIAR [IR];
|
249
|
+
var metricWeightAR = CVSS.Weight.CIAR [AR];
|
250
|
+
var metricWeightMAV = CVSS.Weight.AV [MAV !== "X" ? MAV : AV];
|
251
|
+
var metricWeightMAC = CVSS.Weight.AC [MAC !== "X" ? MAC : AC];
|
252
|
+
var metricWeightMPR = CVSS.Weight.PR [MS !== "X" ? MS : S] [MPR !== "X" ? MPR : PR]; // Depends on MS.
|
253
|
+
var metricWeightMUI = CVSS.Weight.UI [MUI !== "X" ? MUI : UI];
|
254
|
+
var metricWeightMS = CVSS.Weight.S [MS !== "X" ? MS : S];
|
255
|
+
var metricWeightMC = CVSS.Weight.CIA [MC !== "X" ? MC : C];
|
256
|
+
var metricWeightMI = CVSS.Weight.CIA [MI !== "X" ? MI : I];
|
257
|
+
var metricWeightMA = CVSS.Weight.CIA [MA !== "X" ? MA : A];
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
// CALCULATE THE CVSS BASE SCORE
|
262
|
+
|
263
|
+
var baseScore;
|
264
|
+
var impactSubScore;
|
265
|
+
var exploitabalitySubScore = CVSS.exploitabilityCoefficient * metricWeightAV * metricWeightAC * metricWeightPR * metricWeightUI;
|
266
|
+
var impactSubScoreMultiplier = (1 - ((1 - metricWeightC) * (1 - metricWeightI) * (1 - metricWeightA)));
|
267
|
+
|
268
|
+
if (S === 'U') {
|
269
|
+
impactSubScore = metricWeightS * impactSubScoreMultiplier;
|
270
|
+
} else {
|
271
|
+
impactSubScore = metricWeightS * (impactSubScoreMultiplier - 0.029) - 3.25 * Math.pow(impactSubScoreMultiplier - 0.02, 15);
|
272
|
+
}
|
273
|
+
|
274
|
+
if (impactSubScore <= 0) {
|
275
|
+
baseScore = 0;
|
276
|
+
} else {
|
277
|
+
if (S === 'U') {
|
278
|
+
baseScore = CVSS.roundUp1(Math.min((exploitabalitySubScore + impactSubScore), 10));
|
279
|
+
} else {
|
280
|
+
baseScore = CVSS.roundUp1(Math.min((exploitabalitySubScore + impactSubScore) * CVSS.scopeCoefficient, 10));
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
|
285
|
+
|
286
|
+
// CALCULATE THE CVSS TEMPORAL SCORE
|
287
|
+
|
288
|
+
var temporalScore = CVSS.roundUp1(baseScore * metricWeightE * metricWeightRL * metricWeightRC);
|
289
|
+
|
290
|
+
|
291
|
+
// CALCULATE THE CVSS ENVIRONMENTAL SCORE
|
292
|
+
//
|
293
|
+
// - envExploitabalitySubScore recalculates the Base Score Exploitability sub-score using any modified values from the
|
294
|
+
// Environmental metrics group in place of the values specified in the Base Score, if any have been defined.
|
295
|
+
// - envAdjustedImpactSubScore recalculates the Base Score Impact sub-score using any modified values from the
|
296
|
+
// Environmental metrics group in place of the values specified in the Base Score, and any additional weightings
|
297
|
+
// given in the Environmental metrics group.
|
298
|
+
|
299
|
+
var envScore;
|
300
|
+
var envModifiedImpactSubScore;
|
301
|
+
var envModifiedExploitabalitySubScore = CVSS.exploitabilityCoefficient * metricWeightMAV * metricWeightMAC * metricWeightMPR * metricWeightMUI;
|
302
|
+
|
303
|
+
var envImpactSubScoreMultiplier = Math.min (1 - (
|
304
|
+
(1 - metricWeightMC * metricWeightCR) *
|
305
|
+
(1 - metricWeightMI * metricWeightIR) *
|
306
|
+
(1 - metricWeightMA * metricWeightAR)), 0.915);
|
307
|
+
|
308
|
+
if (MS === "U" ||
|
309
|
+
(MS === "X" && S === "U")) {
|
310
|
+
envModifiedImpactSubScore = metricWeightMS * envImpactSubScoreMultiplier;
|
311
|
+
envScore = CVSS.roundUp1(CVSS.roundUp1(Math.min((envModifiedImpactSubScore + envModifiedExploitabalitySubScore), 10)) *
|
312
|
+
metricWeightE * metricWeightRL * metricWeightRC);
|
313
|
+
} else {
|
314
|
+
envModifiedImpactSubScore = metricWeightMS * (envImpactSubScoreMultiplier - 0.029) - 3.25 * Math.pow(envImpactSubScoreMultiplier - 0.02, 15);
|
315
|
+
envScore = CVSS.roundUp1(CVSS.roundUp1(Math.min(CVSS.scopeCoefficient * (envModifiedImpactSubScore + envModifiedExploitabalitySubScore), 10)) *
|
316
|
+
metricWeightE * metricWeightRL * metricWeightRC);
|
317
|
+
}
|
318
|
+
|
319
|
+
if (envModifiedImpactSubScore <= 0) {
|
320
|
+
envScore = 0;
|
321
|
+
}
|
322
|
+
|
323
|
+
|
324
|
+
// CONSTRUCT THE VECTOR STRING
|
325
|
+
|
326
|
+
var vectorString =
|
327
|
+
CVSS.CVSSVersionIdentifier +
|
328
|
+
"/AV:" + AV +
|
329
|
+
"/AC:" + AC +
|
330
|
+
"/PR:" + PR +
|
331
|
+
"/UI:" + UI +
|
332
|
+
"/S:" + S +
|
333
|
+
"/C:" + C +
|
334
|
+
"/I:" + I +
|
335
|
+
"/A:" + A;
|
336
|
+
|
337
|
+
if (E !== "X") {vectorString = vectorString + "/E:" + E;}
|
338
|
+
if (RL !== "X") {vectorString = vectorString + "/RL:" + RL;}
|
339
|
+
if (RC !== "X") {vectorString = vectorString + "/RC:" + RC;}
|
340
|
+
|
341
|
+
if (CR !== "X") {vectorString = vectorString + "/CR:" + CR;}
|
342
|
+
if (IR !== "X") {vectorString = vectorString + "/IR:" + IR;}
|
343
|
+
if (AR !== "X") {vectorString = vectorString + "/AR:" + AR;}
|
344
|
+
if (MAV !== "X") {vectorString = vectorString + "/MAV:" + MAV;}
|
345
|
+
if (MAC !== "X") {vectorString = vectorString + "/MAC:" + MAC;}
|
346
|
+
if (MPR !== "X") {vectorString = vectorString + "/MPR:" + MPR;}
|
347
|
+
if (MUI !== "X") {vectorString = vectorString + "/MUI:" + MUI;}
|
348
|
+
if (MS !== "X") {vectorString = vectorString + "/MS:" + MS;}
|
349
|
+
if (MC !== "X") {vectorString = vectorString + "/MC:" + MC;}
|
350
|
+
if (MI !== "X") {vectorString = vectorString + "/MI:" + MI;}
|
351
|
+
if (MA !== "X") {vectorString = vectorString + "/MA:" + MA;}
|
352
|
+
|
353
|
+
|
354
|
+
// Return an object containing the scores for all three metric groups, and an overall vector string.
|
355
|
+
|
356
|
+
return {
|
357
|
+
success: true,
|
358
|
+
baseMetricScore: baseScore.toFixed(1),
|
359
|
+
baseSeverity: CVSS.severityRating( baseScore.toFixed(1) ),
|
360
|
+
|
361
|
+
temporalMetricScore: temporalScore.toFixed(1),
|
362
|
+
temporalSeverity: CVSS.severityRating( temporalScore.toFixed(1) ),
|
363
|
+
|
364
|
+
environmentalMetricScore: envScore.toFixed(1),
|
365
|
+
environmentalSeverity: CVSS.severityRating( envScore.toFixed(1) ),
|
366
|
+
|
367
|
+
vectorString: vectorString
|
368
|
+
};
|
369
|
+
};
|
370
|
+
|
371
|
+
|
372
|
+
|
373
|
+
|
374
|
+
/* ** CVSS.calculateCVSSFromVector **
|
375
|
+
*
|
376
|
+
* Takes Base, Temporal and Environmental metric values as a single string in the Vector String format defined
|
377
|
+
* in the CVSS v3.0 standard definition of the Vector String.
|
378
|
+
*
|
379
|
+
* Returns Base, Temporal and Environmental scores, severity ratings, and an overall Vector String. All Base metrics
|
380
|
+
* are required to generate this output. All Temporal and Environmental metric values are optional. Any that are not
|
381
|
+
* passed default to "X" ("Not Defined").
|
382
|
+
*
|
383
|
+
* See the comment for the CVSS.calculateCVSSFromMetrics function for details on the function output. In addition to
|
384
|
+
* the error conditions listed for that function, this function can also return:
|
385
|
+
* "MalformedVectorString", if the Vector String passed is does not conform to the format in the standard; or
|
386
|
+
* "MultipleDefinitionsOfMetric", if the Vector String is well formed but defines the same metric (or metrics),
|
387
|
+
* more than once.
|
388
|
+
*/
|
389
|
+
CVSS.calculateCVSSFromVector = function ( vectorString ) {
|
390
|
+
|
391
|
+
var metricValues = {
|
392
|
+
AV: undefined, AC: undefined, PR: undefined, UI: undefined, S: undefined,
|
393
|
+
C: undefined, I: undefined, A: undefined,
|
394
|
+
E: undefined, RL: undefined, RC: undefined,
|
395
|
+
CR: undefined, IR: undefined, AR: undefined,
|
396
|
+
MAV: undefined, MAC: undefined, MPR: undefined, MUI: undefined, MS: undefined,
|
397
|
+
MC: undefined, MI: undefined, MA: undefined
|
398
|
+
};
|
399
|
+
|
400
|
+
// If input validation fails, this array is populated with strings indicating which metrics failed validation.
|
401
|
+
var badMetrics = [];
|
402
|
+
|
403
|
+
if (!CVSS.vectorStringRegex_30.test(vectorString)) {
|
404
|
+
return { success: false, errorType: "MalformedVectorString" };
|
405
|
+
}
|
406
|
+
|
407
|
+
var metricNameValue = vectorString.substring(CVSS.CVSSVersionIdentifier.length).split("/");
|
408
|
+
|
409
|
+
for (var i in metricNameValue) {
|
410
|
+
if (metricNameValue.hasOwnProperty(i)) {
|
411
|
+
|
412
|
+
var singleMetric = metricNameValue[i].split(":");
|
413
|
+
|
414
|
+
if (typeof metricValues[singleMetric[0]] === "undefined") {
|
415
|
+
metricValues[singleMetric[0]] = singleMetric[1];
|
416
|
+
} else {
|
417
|
+
badMetrics.push(singleMetric[0]);
|
418
|
+
}
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
if (badMetrics.length > 0) {
|
423
|
+
return { success: false, errorType: "MultipleDefinitionsOfMetric", errorMetrics: badMetrics };
|
424
|
+
}
|
425
|
+
|
426
|
+
return CVSS.calculateCVSSFromMetrics (
|
427
|
+
metricValues.AV, metricValues.AC, metricValues.PR, metricValues.UI, metricValues.S,
|
428
|
+
metricValues.C, metricValues.I, metricValues.A,
|
429
|
+
metricValues.E, metricValues.RL, metricValues.RC,
|
430
|
+
metricValues.CR, metricValues.IR, metricValues.AR,
|
431
|
+
metricValues.MAV, metricValues.MAC, metricValues.MPR, metricValues.MUI, metricValues.MS,
|
432
|
+
metricValues.MC, metricValues.MI, metricValues.MA);
|
433
|
+
};
|
434
|
+
|
435
|
+
|
436
|
+
|
437
|
+
|
438
|
+
/* ** CVSS.roundUp1 **
|
439
|
+
*
|
440
|
+
* Rounds up the number passed as a parameter to 1 decimal place and returns the result.
|
441
|
+
*
|
442
|
+
* Standard JavaScript errors thrown when arithmetic operations are performed on non-numbers will be returned if the
|
443
|
+
* given input is not a number.
|
444
|
+
*/
|
445
|
+
CVSS.roundUp1 = function (d) {
|
446
|
+
return Math.ceil (d * 10) / 10;
|
447
|
+
};
|
448
|
+
|
449
|
+
|
450
|
+
|
451
|
+
|
452
|
+
/* ** CVSS.severityRating **
|
453
|
+
*
|
454
|
+
* Given a CVSS score, returns the name of the severity rating as defined in the CVSS standard.
|
455
|
+
* The input needs to be a number between 0.0 to 10.0, to one decimal place of precision.
|
456
|
+
*
|
457
|
+
* The following error values may be returned instead of a severity rating name:
|
458
|
+
* NaN (JavaScript "Not a Number") - if the input is not a number.
|
459
|
+
* undefined - if the input is a number that is not within the range of any defined severity rating.
|
460
|
+
*/
|
461
|
+
CVSS.severityRating = function (score) {
|
462
|
+
var severityRatingLength = CVSS.severityRatings.length;
|
463
|
+
|
464
|
+
var validatedScore = Number(score);
|
465
|
+
|
466
|
+
if (isNaN(validatedScore)) {
|
467
|
+
return validatedScore;
|
468
|
+
}
|
469
|
+
|
470
|
+
for (var i = 0; i < severityRatingLength; i++) {
|
471
|
+
if (score >= CVSS.severityRatings[i].bottom && score <= CVSS.severityRatings[i].top) {
|
472
|
+
return CVSS.severityRatings[i].name;
|
473
|
+
}
|
474
|
+
}
|
475
|
+
|
476
|
+
return undefined;
|
477
|
+
};
|
478
|
+
|
479
|
+
|
480
|
+
|
481
|
+
///////////////////////////////////////////////////////////////////////////
|
482
|
+
// DATA AND FUNCTIONS FOR CREATING AN XML REPRESENTATION OF A CVSS SCORE //
|
483
|
+
///////////////////////////////////////////////////////////////////////////
|
484
|
+
|
485
|
+
// A mapping between abbreviated metric values and the string used in the XML representation.
|
486
|
+
// For example, a Remediation Level (RL) abbreviated metric value of "W" maps to "WORKAROUND".
|
487
|
+
// For brevity, Base metric values their modified equivalents in the Environmental metric group. We can do this
|
488
|
+
// because the latter is the same as the former, except it also includes a "NOT_DEFINED" value.
|
489
|
+
|
490
|
+
CVSS.XML_MetricNames = {
|
491
|
+
E: { X: "NOT_DEFINED", U: "UNPROVEN", P: "PROOF_OF_CONCEPT", F: "FUNCTIONAL", H: "HIGH"},
|
492
|
+
RL: { X: "NOT_DEFINED", O: "OFFICIAL_FIX", T: "TEMPORARY_FIX", W: "WORKAROUND", U: "UNAVAILABLE"},
|
493
|
+
RC: { X: "NOT_DEFINED", U: "UNKNOWN", R: "REASONABLE", C: "CONFIRMED"},
|
494
|
+
|
495
|
+
CIAR: { X: "NOT_DEFINED", L: "LOW", M: "MEDIUM", H: "HIGH"}, // CR, IR and AR use the same metric names
|
496
|
+
MAV: { N: "NETWORK", A: "ADJACENT_NETWORK", L: "LOCAL", P: "PHYSICAL", X: "NOT_DEFINED" },
|
497
|
+
MAC: { H: "HIGH", L: "LOW", X: "NOT_DEFINED" },
|
498
|
+
MPR: { N: "NONE", L: "LOW", H: "HIGH", X: "NOT_DEFINED" },
|
499
|
+
MUI: { N: "NONE", R: "REQUIRED", X: "NOT_DEFINED" },
|
500
|
+
MS: { U: "UNCHANGED", C: "CHANGED", X: "NOT_DEFINED" },
|
501
|
+
MCIA: { N: "NONE", L: "LOW", H: "HIGH", X: "NOT_DEFINED" } // C, I and A use the same metric names
|
502
|
+
};
|
503
|
+
|
504
|
+
|
505
|
+
|
506
|
+
/* ** CVSS.generateXMLFromMetrics **
|
507
|
+
*
|
508
|
+
* Takes Base, Temporal and Environmental metric values as individual parameters. Their values are in the short format
|
509
|
+
* defined in the CVSS v3.0 standard definition of the Vector String. For example, the AttackComplexity parameter
|
510
|
+
* should be either "H" or "L".
|
511
|
+
*
|
512
|
+
* Returns a single string containing the metric values in XML form. All Base metrics are required to generate this
|
513
|
+
* output. All Temporal and Environmental metric values are optional. Any that are not passed will be represented in
|
514
|
+
* the XML as NOT_DEFINED. The function returns a string for simplicity. It is arguably better to return the XML as
|
515
|
+
* a DOM object, but at the time of writing this leads to complexity due to older browsers using different JavaScript
|
516
|
+
* interfaces to do this. Also for simplicity, all Temporal and Environmental metrics are include in the string,
|
517
|
+
* even though those with a value of "Not Defined" do not need to be included.
|
518
|
+
*
|
519
|
+
* The output of this function is an object which always has a property named "success".
|
520
|
+
*
|
521
|
+
* If no errors are encountered, success is Boolean "true", and the "xmlString" property contains the XML string
|
522
|
+
* representation.
|
523
|
+
*
|
524
|
+
* If errors are encountered, success is Boolean "false", and other properties are defined as per the
|
525
|
+
* CVSS.calculateCVSSFromMetrics function. Refer to the comment for that function for more details.
|
526
|
+
*/
|
527
|
+
CVSS.generateXMLFromMetrics = function (
|
528
|
+
AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope, Confidentiality, Integrity, Availability,
|
529
|
+
ExploitCodeMaturity, RemediationLevel, ReportConfidence,
|
530
|
+
ConfidentialityRequirement, IntegrityRequirement, AvailabilityRequirement,
|
531
|
+
ModifiedAttackVector, ModifiedAttackComplexity, ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
|
532
|
+
ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability) {
|
533
|
+
|
534
|
+
// A string containing the XML we wish to output, with placeholders for the CVSS metrics we will substitute for
|
535
|
+
// their values, based on the inputs passed to this function.
|
536
|
+
var xmlTemplate =
|
537
|
+
'<?xml version="1.0" encoding="UTF-8"?>\n' +
|
538
|
+
'<cvssv3.0 xmlns="https://www.first.org/cvss/cvss-v3.0.xsd"\n' +
|
539
|
+
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' +
|
540
|
+
' xsi:schemaLocation="https://www.first.org/cvss/cvss-v3.0.xsd https://www.first.org/cvss/cvss-v3.0.xsd"\n' +
|
541
|
+
' >\n' +
|
542
|
+
'\n' +
|
543
|
+
' <base_metrics>\n' +
|
544
|
+
' <attack-vector>__AttackVector__</attack-vector>\n' +
|
545
|
+
' <attack-complexity>__AttackComplexity__</attack-complexity>\n' +
|
546
|
+
' <privileges-required>__PrivilegesRequired__</privileges-required>\n' +
|
547
|
+
' <user-interaction>__UserInteraction__</user-interaction>\n' +
|
548
|
+
' <scope>__Scope__</scope>\n' +
|
549
|
+
' <confidentiality-impact>__Confidentiality__</confidentiality-impact>\n' +
|
550
|
+
' <integrity-impact>__Integrity__</integrity-impact>\n' +
|
551
|
+
' <availability-impact>__Availability__</availability-impact>\n' +
|
552
|
+
' <base-score>__BaseScore__</base-score>\n' +
|
553
|
+
' <base-severity>__BaseSeverityRating__</base-severity>\n' +
|
554
|
+
' </base_metrics>\n' +
|
555
|
+
'\n' +
|
556
|
+
' <temporal_metrics>\n' +
|
557
|
+
' <exploit-code-maturity>__ExploitCodeMaturity__</exploit-code-maturity>\n' +
|
558
|
+
' <remediation-level>__RemediationLevel__</remediation-level>\n' +
|
559
|
+
' <report-confidence>__ReportConfidence__</report-confidence>\n' +
|
560
|
+
' <temporal-score>__TemporalScore__</temporal-score>\n' +
|
561
|
+
' <temporal-severity>__TemporalSeverityRating__</temporal-severity>\n' +
|
562
|
+
' </temporal_metrics>\n' +
|
563
|
+
'\n' +
|
564
|
+
' <environmental_metrics>\n' +
|
565
|
+
' <confidentiality-requirement>__ConfidentialityRequirement__</confidentiality-requirement>\n' +
|
566
|
+
' <integrity-requirement>__IntegrityRequirement__</integrity-requirement>\n' +
|
567
|
+
' <availability-requirement>__AvailabilityRequirement__</availability-requirement>\n' +
|
568
|
+
' <modified-attack-vector>__ModifiedAttackVector__</modified-attack-vector>\n' +
|
569
|
+
' <modified-attack-complexity>__ModifiedAttackComplexity__</modified-attack-complexity>\n' +
|
570
|
+
' <modified-privileges-required>__ModifiedPrivilegesRequired__</modified-privileges-required>\n' +
|
571
|
+
' <modified-user-interaction>__ModifiedUserInteraction__</modified-user-interaction>\n' +
|
572
|
+
' <modified-scope>__ModifiedScope__</modified-scope>\n' +
|
573
|
+
' <modified-confidentiality-impact>__ModifiedConfidentiality__</modified-confidentiality-impact>\n' +
|
574
|
+
' <modified-integrity-impact>__ModifiedIntegrity__</modified-integrity-impact>\n' +
|
575
|
+
' <modified-availability-impact>__ModifiedAvailability__</modified-availability-impact>\n' +
|
576
|
+
' <environmental-score>__EnvironmentalScore__</environmental-score>\n' +
|
577
|
+
' <environmental-severity>__EnvironmentalSeverityRating__</environmental-severity>\n' +
|
578
|
+
' </environmental_metrics>\n' +
|
579
|
+
'\n' +
|
580
|
+
'</cvssv3.0>\n';
|
581
|
+
|
582
|
+
|
583
|
+
// Call CVSS.calculateCVSSFromMetrics to validate all the parameters and generate scores and severity ratings.
|
584
|
+
// If that function returns an error, immediately return it to the caller of this function.
|
585
|
+
var result = CVSS.calculateCVSSFromMetrics (
|
586
|
+
AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope, Confidentiality, Integrity, Availability,
|
587
|
+
ExploitCodeMaturity, RemediationLevel, ReportConfidence,
|
588
|
+
ConfidentialityRequirement, IntegrityRequirement, AvailabilityRequirement,
|
589
|
+
ModifiedAttackVector, ModifiedAttackComplexity, ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
|
590
|
+
ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability);
|
591
|
+
|
592
|
+
if (result.success !== true) {
|
593
|
+
return result;
|
594
|
+
}
|
595
|
+
|
596
|
+
var xmlOutput = xmlTemplate;
|
597
|
+
xmlOutput = xmlOutput.replace ("__AttackVector__", CVSS.XML_MetricNames["MAV"][AttackVector]);
|
598
|
+
xmlOutput = xmlOutput.replace ("__AttackComplexity__", CVSS.XML_MetricNames["MAC"][AttackComplexity]);
|
599
|
+
xmlOutput = xmlOutput.replace ("__PrivilegesRequired__", CVSS.XML_MetricNames["MPR"][PrivilegesRequired]);
|
600
|
+
xmlOutput = xmlOutput.replace ("__UserInteraction__", CVSS.XML_MetricNames["MUI"][UserInteraction]);
|
601
|
+
xmlOutput = xmlOutput.replace ("__Scope__", CVSS.XML_MetricNames["MS"][Scope]);
|
602
|
+
xmlOutput = xmlOutput.replace ("__Confidentiality__", CVSS.XML_MetricNames["MCIA"][Confidentiality]);
|
603
|
+
xmlOutput = xmlOutput.replace ("__Integrity__", CVSS.XML_MetricNames["MCIA"][Integrity]);
|
604
|
+
xmlOutput = xmlOutput.replace ("__Availability__", CVSS.XML_MetricNames["MCIA"][Availability]);
|
605
|
+
xmlOutput = xmlOutput.replace ("__BaseScore__", result.baseMetricScore);
|
606
|
+
xmlOutput = xmlOutput.replace ("__BaseSeverityRating__", result.baseSeverity);
|
607
|
+
|
608
|
+
xmlOutput = xmlOutput.replace ("__ExploitCodeMaturity__", CVSS.XML_MetricNames["E"][ExploitCodeMaturity || "X"]);
|
609
|
+
xmlOutput = xmlOutput.replace ("__RemediationLevel__", CVSS.XML_MetricNames["RL"][RemediationLevel || "X"]);
|
610
|
+
xmlOutput = xmlOutput.replace ("__ReportConfidence__", CVSS.XML_MetricNames["RC"][ReportConfidence || "X"]);
|
611
|
+
xmlOutput = xmlOutput.replace ("__TemporalScore__", result.temporalMetricScore);
|
612
|
+
xmlOutput = xmlOutput.replace ("__TemporalSeverityRating__", result.temporalSeverity);
|
613
|
+
|
614
|
+
xmlOutput = xmlOutput.replace ("__ConfidentialityRequirement__", CVSS.XML_MetricNames["CIAR"][ConfidentialityRequirement || "X"]);
|
615
|
+
xmlOutput = xmlOutput.replace ("__IntegrityRequirement__", CVSS.XML_MetricNames["CIAR"][IntegrityRequirement || "X"]);
|
616
|
+
xmlOutput = xmlOutput.replace ("__AvailabilityRequirement__", CVSS.XML_MetricNames["CIAR"][AvailabilityRequirement || "X"]);
|
617
|
+
xmlOutput = xmlOutput.replace ("__ModifiedAttackVector__", CVSS.XML_MetricNames["MAV"][ModifiedAttackVector || "X"]);
|
618
|
+
xmlOutput = xmlOutput.replace ("__ModifiedAttackComplexity__", CVSS.XML_MetricNames["MAC"][ModifiedAttackComplexity || "X"]);
|
619
|
+
xmlOutput = xmlOutput.replace ("__ModifiedPrivilegesRequired__", CVSS.XML_MetricNames["MPR"][ModifiedPrivilegesRequired || "X"]);
|
620
|
+
xmlOutput = xmlOutput.replace ("__ModifiedUserInteraction__", CVSS.XML_MetricNames["MUI"][ModifiedUserInteraction || "X"]);
|
621
|
+
xmlOutput = xmlOutput.replace ("__ModifiedScope__", CVSS.XML_MetricNames["MS"][ModifiedScope || "X"]);
|
622
|
+
xmlOutput = xmlOutput.replace ("__ModifiedConfidentiality__", CVSS.XML_MetricNames["MCIA"][ModifiedConfidentiality || "X"]);
|
623
|
+
xmlOutput = xmlOutput.replace ("__ModifiedIntegrity__", CVSS.XML_MetricNames["MCIA"][ModifiedIntegrity || "X"]);
|
624
|
+
xmlOutput = xmlOutput.replace ("__ModifiedAvailability__", CVSS.XML_MetricNames["MCIA"][ModifiedAvailability || "X"]);
|
625
|
+
xmlOutput = xmlOutput.replace ("__EnvironmentalScore__", result.environmentalMetricScore);
|
626
|
+
xmlOutput = xmlOutput.replace ("__EnvironmentalSeverityRating__", result.environmentalSeverity);
|
627
|
+
|
628
|
+
return { success: true, xmlString: xmlOutput };
|
629
|
+
};
|
630
|
+
|
631
|
+
|
632
|
+
|
633
|
+
/* ** CVSS.generateXMLFromVector **
|
634
|
+
*
|
635
|
+
* Takes Base, Temporal and Environmental metric values as a single string in the Vector String format defined
|
636
|
+
* in the CVSS v3.0 standard definition of the Vector String.
|
637
|
+
*
|
638
|
+
* Returns an XML string representation of this input. See the comment for CVSS.generateXMLFromMetrics for more
|
639
|
+
* detail on inputs, return values and errors. In addition to the error conditions listed for that function, this
|
640
|
+
* function can also return:
|
641
|
+
* "MalformedVectorString", if the Vector String passed is does not conform to the format in the standard; or
|
642
|
+
* "MultipleDefinitionsOfMetric", if the Vector String is well formed but defines the same metric (or metrics),
|
643
|
+
* more than once.
|
644
|
+
*/
|
645
|
+
CVSS.generateXMLFromVector = function ( vectorString ) {
|
646
|
+
|
647
|
+
var metricValues = {
|
648
|
+
AV: undefined, AC: undefined, PR: undefined, UI: undefined, S: undefined,
|
649
|
+
C: undefined, I: undefined, A: undefined,
|
650
|
+
E: undefined, RL: undefined, RC: undefined,
|
651
|
+
CR: undefined, IR: undefined, AR: undefined,
|
652
|
+
MAV: undefined, MAC: undefined, MPR: undefined, MUI: undefined, MS: undefined,
|
653
|
+
MC: undefined, MI: undefined, MA: undefined
|
654
|
+
};
|
655
|
+
|
656
|
+
// If input validation fails, this array is populated with strings indicating which metrics failed validation.
|
657
|
+
var badMetrics = [];
|
658
|
+
|
659
|
+
if (!CVSS.vectorStringRegex_30.test(vectorString)) {
|
660
|
+
return { success: false, errorType: "MalformedVectorString" };
|
661
|
+
}
|
662
|
+
|
663
|
+
var metricNameValue = vectorString.substring(CVSS.CVSSVersionIdentifier.length).split("/");
|
664
|
+
|
665
|
+
for (var i in metricNameValue) {
|
666
|
+
if (metricNameValue.hasOwnProperty(i)) {
|
667
|
+
|
668
|
+
var singleMetric = metricNameValue[i].split(":");
|
669
|
+
|
670
|
+
if (typeof metricValues[singleMetric[0]] === "undefined") {
|
671
|
+
metricValues[singleMetric[0]] = singleMetric[1];
|
672
|
+
} else {
|
673
|
+
badMetrics.push(singleMetric[0]);
|
674
|
+
}
|
675
|
+
}
|
676
|
+
}
|
677
|
+
|
678
|
+
if (badMetrics.length > 0) {
|
679
|
+
return { success: false, errorType: "MultipleDefinitionsOfMetric", errorMetrics: badMetrics };
|
680
|
+
}
|
681
|
+
|
682
|
+
return CVSS.generateXMLFromMetrics (
|
683
|
+
metricValues.AV, metricValues.AC, metricValues.PR, metricValues.UI, metricValues.S,
|
684
|
+
metricValues.C, metricValues.I, metricValues.A,
|
685
|
+
metricValues.E, metricValues.RL, metricValues.RC,
|
686
|
+
metricValues.CR, metricValues.IR, metricValues.AR,
|
687
|
+
metricValues.MAV, metricValues.MAC, metricValues.MPR, metricValues.MUI, metricValues.MS,
|
688
|
+
metricValues.MC, metricValues.MI, metricValues.MA);
|
689
|
+
};
|