File Coverage

blib/lib/CVSS/v2.pm
Criterion Covered Total %
statement 65 81 80.2
branch 6 12 50.0
condition 7 14 50.0
subroutine 17 20 85.0
pod 10 11 90.9
total 105 138 76.0


line stmt bran cond sub pod time code
1             package CVSS::v2;
2              
3 3     3   83276 use feature ':5.10';
  3         6  
  3         490  
4 3     3   18 use strict;
  3         4  
  3         68  
5 3     3   419 use utf8;
  3         256  
  3         13  
6 3     3   99 use warnings;
  3         6  
  3         118  
7              
8 3     3   13 use Carp ();
  3         4  
  3         73  
9 3     3   12 use List::Util qw(min);
  3         5  
  3         209  
10              
11 3     3   16 use base 'CVSS::Base';
  3         4  
  3         1875  
12 3     3   1731 use CVSS::Constants ();
  3         13  
  3         256  
13              
14             our $VERSION = '1.14';
15             $VERSION =~ tr/_//d; ## no critic
16              
17 3     3   19 use constant DEBUG => $ENV{CVSS_DEBUG};
  3         8  
  3         3648  
18              
19             my $WEIGHTS = CVSS::Constants->CVSS2_WEIGHTS;
20              
21 2     2 1 18 sub ATTRIBUTES { CVSS::Constants->CVSS2_ATTRIBUTES }
22 0     0 1 0 sub SCORE_SEVERITY { CVSS::Constants->CVSS2_SCORE_SEVERITY }
23 3680     3680 1 15474 sub NOT_DEFINED_VALUE { CVSS::Constants->CVSS2_NOT_DEFINED_VALUE }
24 368     368 1 5531 sub VECTOR_STRING_REGEX { CVSS::Constants->CVSS2_VECTOR_STRING_REGEX }
25 2576     2576 1 14905 sub METRIC_GROUPS { CVSS::Constants->CVSS2_METRIC_GROUPS }
26 0     0 1 0 sub METRIC_NAMES { CVSS::Constants->CVSS2_METRIC_NAMES }
27 0     0 1 0 sub METRIC_VALUES { CVSS::Constants->CVSS2_METRIC_VALUES }
28              
29 736     736 1 5550 sub version {'2.0'}
30              
31             sub weight {
32              
33 2208     2208 0 3899 my ($self, $metric) = @_;
34              
35 2208         4897 my $value = $self->M($metric);
36 2208         4291 my $weight = $WEIGHTS->{$metric}{$value};
37              
38 2208         2730 DEBUG and say STDERR "-- Weight : $metric:$value = $weight";
39 2208         5693 return $weight;
40              
41             }
42              
43 2208     2208 1 4065 sub W { weight(@_) }
44              
45             sub calculate_score {
46              
47 368     368 1 847 my ($self, $args) = @_;
48              
49 368 50       548 if (%{$self->metrics}) {
  368         949  
50 368         633 for (@{$self->METRIC_GROUPS->{base}}) {
  368         2307  
51 2208 50       4191 Carp::croak sprintf('Missing base metric (%s)', $_) unless ($self->metrics->{$_});
52             }
53             }
54              
55             # Set NOT_DEFINED
56 368   50     822 $self->metrics->{E} //= 'ND';
57 368   50     757 $self->metrics->{RL} //= 'ND';
58 368   50     800 $self->metrics->{RC} //= 'ND';
59              
60 368   50     743 $self->metrics->{TD} //= 'ND';
61 368   50     734 $self->metrics->{CR} //= 'ND';
62 368   50     825 $self->metrics->{IR} //= 'ND';
63 368   50     824 $self->metrics->{AR} //= 'ND';
64              
65             # Base Equation
66              
67             # BaseScore = round_to_1_decimal(((0.6*Impact)+(0.4*Exploitability)-1.5)*f(Impact))
68             # Impact = 10.41*(1-(1-ConfImpact)*(1-IntegImpact)*(1-AvailImpact))
69             # Exploitability = 20* AccessVector*AccessComplexity*Authentication
70             # f(impact)= 0 if Impact=0, 1.176 otherwise
71              
72 368         1037 my $impact = (10.41 * (1 - (1 - $self->W('C')) * (1 - $self->W('I')) * (1 - $self->W('A'))));
73 368         739 my $exploitability = (20 * $self->W('AV') * $self->W('AC') * $self->W('Au'));
74 368 100       1036 my $f_impact = ($impact == 0 ? 0 : 1.176);
75 368         2808 my $base_score = sprintf('%.1f', (((0.6 * $impact) + (0.4 * $exploitability) - 1.5) * $f_impact));
76              
77 368         503 DEBUG and say STDERR "-- Impact: $impact";
78 368         444 DEBUG and say STDERR "-- f(Impact): $f_impact";
79 368         516 DEBUG and say STDERR "-- Exploitability: $exploitability";
80 368         478 DEBUG and say STDERR "-- BaseScore: $base_score";
81              
82 368         1866 $self->{scores}->{impact} = sprintf('%.1f', $impact);
83 368         970 $self->{scores}->{base} = $base_score;
84 368         1175 $self->{scores}->{exploitability} = sprintf('%.1f', $exploitability);
85              
86 368 50       1087 if ($self->metric_group_is_set('temporal')) {
87              
88             # Temporal Equation
89              
90             # TemporalScore = round_to_1_decimal(BaseScore * Exploitability * RemediationLevel * ReportConfidence)
91              
92 0         0 my $temporal_score = sprintf('%.1f', ($base_score * $self->W('E') * $self->W('RL') * $self->W('RC')));
93              
94 0         0 DEBUG and say STDERR "-- TemporalScore: $temporal_score";
95              
96 0         0 $self->{scores}->{temporal} = $temporal_score;
97              
98             }
99              
100 368 50       884 if ($self->M('CDP')) {
101              
102             # Environmental Equation
103              
104             # EnvironmentalScore = round_to_1_decimal((AdjustedTemporal+
105             # (10-AdjustedTemporal)*CollateralDamagePotential)*TargetDistribution)
106              
107             # AdjustedTemporal = TemporalScore recomputed with the BaseScore's Impact sub-
108             # equation replaced with the AdjustedImpact equation
109              
110             # AdjustedImpact = min(10,10.41*(1-(1-ConfImpact*ConfReq)*(1-IntegImpact*IntegReq)
111             # *(1-AvailImpact*AvailReq)))
112              
113             # AdjustedTemporal = quickRound(AdjustedBaseScore * Exploitability * RemediationLevel * ReportConfidence)
114             # AdjustedBaseScore = quickRound((0.6 * AdjustedImpact + 0.4 * Exploitability - 1.5) * f(Impact))
115              
116 0         0 my $adj_impact = min(
117             10,
118             10.41 * (
119             1 - (1 - $self->W('C') * $self->W('CR'))
120             * (1 - $self->W('I') * $self->W('IR'))
121             * (1 - $self->W('A') * $self->W('AR'))
122             )
123             );
124              
125 0 0       0 $adj_impact = 10 if ($adj_impact > 10);
126              
127 0         0 my $adj_base_score = ((0.6 * $adj_impact + 0.4 * $exploitability - 1.5) * $f_impact);
128 0         0 my $adj_temporal = ($adj_base_score * $self->W('E') * $self->W('RL') * $self->W('RC'));
129              
130 0         0 my $environmental_score
131             = sprintf('%.1f', (($adj_temporal + (10 - $adj_temporal) * $self->W('CDP')) * $self->W('TD')));
132              
133 0         0 DEBUG and say STDERR "-- AdjustedImpact: $adj_impact";
134 0         0 DEBUG and say STDERR "-- AdjustedTemporal: $adj_temporal";
135 0         0 DEBUG and say STDERR "-- EnvironmentalScore: $environmental_score";
136              
137 0         0 $self->{scores}->{environmental} = $environmental_score;
138 0         0 $self->{scores}->{modified_impact} = sprintf('%.1f', $adj_impact);
139              
140             }
141              
142 368         938 return 1;
143              
144             }
145              
146             1;
147             __END__