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   124784 use feature ':5.10';
  3         7  
  3         443  
4 3     3   21 use strict;
  3         5  
  3         100  
5 3     3   647 use utf8;
  3         351  
  3         17  
6 3     3   120 use warnings;
  3         6  
  3         136  
7              
8 3     3   15 use Carp ();
  3         5  
  3         126  
9 3     3   16 use List::Util qw(min);
  3         5  
  3         267  
10              
11 3     3   20 use base 'CVSS::Base';
  3         18  
  3         1624  
12 3     3   1867 use CVSS::Constants ();
  3         13  
  3         300  
13              
14             our $VERSION = '1.15';
15             $VERSION =~ tr/_//d; ## no critic
16              
17 3     3   23 use constant DEBUG => $ENV{CVSS_DEBUG};
  3         7  
  3         3641  
18              
19             my $WEIGHTS = CVSS::Constants->CVSS2_WEIGHTS;
20              
21 4     4 1 38 sub ATTRIBUTES { CVSS::Constants->CVSS2_ATTRIBUTES }
22 0     0 1 0 sub SCORE_SEVERITY { CVSS::Constants->CVSS2_SCORE_SEVERITY }
23 3680     3680 1 10939 sub NOT_DEFINED_VALUE { CVSS::Constants->CVSS2_NOT_DEFINED_VALUE }
24 368     368 1 4320 sub VECTOR_STRING_REGEX { CVSS::Constants->CVSS2_VECTOR_STRING_REGEX }
25 2576     2576 1 9107 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 4139 sub version {'2.0'}
30              
31             sub weight {
32              
33 2208     2208 0 2732 my ($self, $metric) = @_;
34              
35 2208         3343 my $value = $self->M($metric);
36 2208         3358 my $weight = $WEIGHTS->{$metric}{$value};
37              
38 2208         2133 DEBUG and say STDERR "-- Weight : $metric:$value = $weight";
39 2208         4264 return $weight;
40              
41             }
42              
43 2208     2208 1 2875 sub W { weight(@_) }
44              
45             sub calculate_score {
46              
47 368     368 1 624 my ($self, $args) = @_;
48              
49 368 50       416 if (%{$self->metrics}) {
  368         683  
50 368         481 for (@{$self->METRIC_GROUPS->{base}}) {
  368         601  
51 2208 50       3051 Carp::croak sprintf('Missing base metric (%s)', $_) unless ($self->metrics->{$_});
52             }
53             }
54              
55             # Set NOT_DEFINED
56 368   50     673 $self->metrics->{E} //= 'ND';
57 368   50     816 $self->metrics->{RL} //= 'ND';
58 368   50     554 $self->metrics->{RC} //= 'ND';
59              
60 368   50     550 $self->metrics->{TD} //= 'ND';
61 368   50     620 $self->metrics->{CR} //= 'ND';
62 368   50     555 $self->metrics->{IR} //= 'ND';
63 368   50     537 $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         705 my $impact = (10.41 * (1 - (1 - $self->W('C')) * (1 - $self->W('I')) * (1 - $self->W('A'))));
73 368         552 my $exploitability = (20 * $self->W('AV') * $self->W('AC') * $self->W('Au'));
74 368 100       783 my $f_impact = ($impact == 0 ? 0 : 1.176);
75 368         2391 my $base_score = sprintf('%.1f', (((0.6 * $impact) + (0.4 * $exploitability) - 1.5) * $f_impact));
76              
77 368         376 DEBUG and say STDERR "-- Impact: $impact";
78 368         344 DEBUG and say STDERR "-- f(Impact): $f_impact";
79 368         344 DEBUG and say STDERR "-- Exploitability: $exploitability";
80 368         328 DEBUG and say STDERR "-- BaseScore: $base_score";
81              
82 368         1277 $self->{scores}->{impact} = sprintf('%.1f', $impact);
83 368         635 $self->{scores}->{base} = $base_score;
84 368         857 $self->{scores}->{exploitability} = sprintf('%.1f', $exploitability);
85              
86 368 50       641 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       682 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         599 return 1;
143              
144             }
145              
146             1;
147             __END__