summaryrefslogtreecommitdiffstats
path: root/bin/compare-nvd-cve
blob: a74a0074da5fb69dd7fd37f85837333158314b75 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/perl
#
# Compare the Debian list of CVEs with the NVD list of CVEs using CPE
# ids, to see if the set of affected packages match.

use warnings;
use strict;

use XML::Simple;
use Data::Dumper;

use vars qw($debug %cpemap %cperevmap %cvemap %reportedmissing);

$| = 1;

open(my $fh, "<", "data/CPE/list") || die;
while (<$fh>) {
    chomp;
    my ($binpkg, $cpe) = split(/;/);
    if ($cpe) {
        $cpemap{$binpkg} = $cpe;
        $cperevmap{$cpe} = $binpkg;
    }
}
close $fh;

open ($fh, "<", "data/CVE/list") || die;
my $cve;
while (<$fh>) {
    chomp;
    $cve = $1 if (m/^(CVE-\S+)\s*/);
    s/^(\s+)\[\S+\] /$1/; # Trim away distribution name
    if (m/^\s+- (\S+)\S*/ && ! m/<not-affected>/) {
        my $srcpkg = $1;
        if (exists $cvemap{$cve}) {
            push(@{$cvemap{$cve}}, $srcpkg);
        } else {
            $cvemap{$cve} = [$srcpkg];
        }
    }
}
close $fh;

#
# Fetched from http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2008.xml
#
for my $cvelist
    (
     "nvdcve-2.0-2011.xml",
#     "nvdcve-2.0-2010.xml",
#     "nvdcve-2.0-2009.xml",
#     "nvdcve-2.0-2008.xml",
    ) {
    print "Loading $cvelist\n" if $debug;
    my $ref = XMLin("../../" . $cvelist);
    for my $cve (sort keys %{$ref->{entry}}) {
        print "Checking $cve\n" if $debug;
        my $entry = $ref->{entry}->{$cve};

        my %info;
        my @debiancpe = get_debian_cpe($cve);
        for my $cpe (@debiancpe) {
            $info{$cpe} = 1;
        }

        my @products;
        if (exists $entry->{'vuln:vulnerable-software-list'}->{'vuln:product'}) {
            if ("ARRAY" eq ref $entry->{'vuln:vulnerable-software-list'}->{'vuln:product'}) {
                @products = @{$entry->{'vuln:vulnerable-software-list'}->{'vuln:product'}};
            } else {
                @products = ($entry->{'vuln:vulnerable-software-list'}->{'vuln:product'});
            }
        }
        for my $cpe (@products) {
            if (exists $info{cpe_product($cpe)}) {
                $info{cpe_product($cpe)} += 2;
            } else {
                $info{cpe_product($cpe)} = 2;
            }
        }
        for my $cpe (sort keys %info) {
            if (1 == $info{$cpe}) {
                my %shortlist;
                map { $shortlist{cpe_product($_)} = 1 } @products;
                my $cpelist = join(", ", keys %shortlist);
                print STDERR "warning: $cve in Debian refer to $cpe, while NVD do not (found $cpelist).\n"
            } elsif (2 == $info{$cpe}) {
                if (exists $cperevmap{$cpe}) {
                    my $binpkg = $cperevmap{$cpe};
                    print STDERR "warning: $cve in NVD is not refering to $cpe found in Debian.\n"
                }

            } elsif (3 == $info{$cpe}) {
            }
        }
    }
    print "Done loading $cvelist\n" if $debug;
}

for my $missing (sort { $reportedmissing{$a} <=> $reportedmissing{$b} }
                 keys %reportedmissing) {
    my $count = $reportedmissing{$missing};
    print STDERR "error: $cve: missing CPE ID for $missing ($count)\n";
}

sub get_debian_cpe {
    my ($cve) = shift;
    my %cpe;
    for my $binpkg (@{$cvemap{$cve}}) {
        if (exists $cpemap{$binpkg}) {
            $cpe{$cpemap{$binpkg}} = 1;
        } else {
            $reportedmissing{$binpkg} = exists $reportedmissing{$binpkg} ?
                $reportedmissing{$binpkg} + 1 : 1;
        }
    }
    return sort keys %cpe;
}

sub cpe_product {
    my $cpe = shift;
    return join(":", (split(/:/, $cpe))[0..3]);
}

© 2014-2024 Faster IT GmbH | imprint | privacy policy