#!/usr/bin/perl # # parse-nsr.pl # # Parse Nessus NSR files and spit out data by host, # suitable for comparing with diff or further processing # by a database or spreadsheeet. # # Outputs TAB separate columns as follows: # # ipaddress hostname risk-factor port plugin-id # # Output is sorted by host IP address. # # Based on a script originally posted to the Nessus mailing # list by Darren Bounds # (http://mail.nessus.org/pipermail/nessus/2004-March/msg00243.html) # use Socket; if ( !$ARGV[0] ) { print "Usage: $0 \n"; exit; } open NSR, "<$ARGV[0]" or die "Error opening NSR file: $!\n"; while ( my $line = ) { my ( $ip_address, $service, $plugin, $type, $info ) = split /\|/, $line; # Skip useless lines (e.g. ones with just IP and port but no other data) next unless defined $plugin; # Skip unless plugin is a numerical value and type is "report" or "info" next if ( $plugin eq "" || $plugin !~ /[0-9]/ || ( $type ne "REPORT" && $type ne "INFO" ) ); if ( $info =~ /Risk factor :/ ) { undef $solution; undef $risk; undef $cve; undef $bid; undef $other; undef $description; # 'Risk factor' doesn't always appear in the right field in NSR files. # The following crude regexp seems to catch it everytime: $info =~ /Risk factor :\W+(\w+)/; $risk = $1; # Attempt to parse the rest of the "info" field: my @info_array = split /\;/, $info; $info_done = 0; foreach $item (@info_array) { if ( $item =~ /^Solution/ ) { $item =~ s/Solution://g; $solution = $item; $info_done = 1; } elsif ( $item =~ /^CVE/ ) { $cve = $item; $info_done = 1; } elsif ( $item =~ /^BID/ ) { $bid = $item; $info_done = 1; } elsif ( $item =~ /^Other references/ ) { $other = $item; $info_done = 1; } elsif ( $info_done == 0 ) { $description = $description . " " . $item; } } $description =~ s/ / /g; # Try to resolve hostname: $hostname = $ip_address; $hname = gethostbyaddr( inet_aton($hostname), AF_INET ); $hostname = $hname if $hname; } # Add to an array so we can sort it later: # Use tab separated columns (easy to diff, read into a spreadsheet, etc) push @vulnlist, "$ip_address\t$hostname\t$risk\t$service\t$plugin\n"; } close NSR; # Sort the array by first column then print: my @sorted = sort (@vulnlist); foreach $dataline (@sorted) { print $dataline; }