Nessus Parser v15
December 5th, 2011
Greetings All,
Here is a maintenance release of the Nessus parser. I would like to make a special shout out to Joe M (joebeast20 – AT – yahoo.com) for finding a bug and contributing the code. The bug Joe found were missing plugin families in the check and reporting functions. I took the opportunity to update the plugin families so all plugin families are now in the tool.
Thanks again Joe.
parse_nessus_xml.v15.pl
This is a great tool, thank you for developing it.
I’m using Nessus v5 and notice that when parsing the “critical” vulnerabilities are not counted as the logic is based on H/M/L. For now, I modified the if statement for High to include 3 or 4, but was wondering if you might be working on integrating this new “level” into a future version of the script.
Thanks again for the excellent tool.
I am going to update the parser, just have really crazy work schedule right now. Hopefully I will be able to update the parser soon.
Here’s an patch to an updated version that supports crit vulns and fixes some typos. I haven’t used it before v15, so I’m not sure if the fact that I’m getting 0s for “Total count of” and “Number of systems with” is something I broke, a Nessus 5 thing, or if it’s always been that way.
===cut===
39c39
our (@vuln_entries,@critvuln,@highvuln,@medvuln,@lowvuln,@nonevuln,@host_scan_data);
40a41
> our $critvuln_cnt = 0;
118c119
This command will search the directory specified by the “-d” option
235a237
> my $sev4 = grep {$_->{-severity} == 4} @vuln_array;
239a242
> $vuln_cnt{sev4} = $vuln_cnt{sev4} + $sev4;
244c247,248
$sev3
—
> sev3 => $sev3,
> sev4 => $sev4
532a537,565
> elsif ($severity == 4)
> {
> my $plugin_test = grep /$vuln->{-pluginID}/, @critvuln;
> my @found_plugin = grep /$vuln->{-pluginID}/, @critvuln;
> if ($plugin_test == 0)
> {
> ++$plugin_cnt;
> $plugin = “$plugin\,$severity\,$plugin_cnt\,$pluginName\,$file\,$vuln->{-pluginFamily},$bid,$cve,$xref,$vuln->{solution},$vuln->{description}”;
> push @critvuln, $plugin
> }
> else
> {
> foreach (@critvuln)
> {
> my @tmp = split /\,/, $_;
> if ($tmp[0] eq $vuln->{-pluginID} && $tmp[4] ne $file && $plugin_test == 1)
> {
> $plugin = “$plugin\,$severity\,$plugin_cnt\,$pluginName\,$file\,$vuln->{-pluginFamily},$bid,$cve,$xref,$vuln->{solution},$vuln->{description}”;
> push @critvuln, $plugin
> }
> elsif ($tmp[0] eq $vuln->{-pluginID} && $tmp[4] eq $file)
> {
> ++$tmp[2];
> $_ = join(“,”,@tmp);
> last;
> }
> } # end foreach
> } #end else for test
> }
875a909
> $vuln_cnt{sev4} = 0;
1220a1255,1290
> my $critvulns_ctr = 2;
> print “Storing Critical Severity Data Table\n”;
> my $critvulns_worksheet = $workbook->add_worksheet(‘critvulns’);
> $critvulns_worksheet->write_url( ‘A1’, $home_url, $url_format, $_);
> $critvulns_worksheet->keep_leading_zeros();
> $critvulns_worksheet->write(1, 0, ‘File’);
> $critvulns_worksheet->write(1, 1, ‘plugin Family’);
> $critvulns_worksheet->write(1, 2, ‘plugin id’);
> $critvulns_worksheet->write(1, 3, ‘plugin Name’);
> $critvulns_worksheet->write(1, 4, ‘count’);
> $critvulns_worksheet->write(1, 5, ‘Bid’);
> $critvulns_worksheet->write(1, 6, ‘CVE’);
> $critvulns_worksheet->write(1, 7, ‘OSVDB’);
> $critvulns_worksheet->write(1, 8, ‘Solution’);
> $critvulns_worksheet->write(1, 9, ‘Description’);
> $critvulns_worksheet->freeze_panes(‘C3’);
> $critvulns_worksheet->autofilter(‘A2:J2’);
> $critvulns_worksheet->set_column(‘A:M’, 20);
>
> foreach (@critvuln)
> {
> my @tmp = split /\,/, $_;
> $critvulns_worksheet->write($critvulns_ctr, 0, $tmp[4]);
> $critvulns_worksheet->write($critvulns_ctr, 1, $tmp[5]);
> $critvulns_worksheet->write($critvulns_ctr, 2, $tmp[0]);
> $critvulns_worksheet->write($critvulns_ctr, 3, $tmp[3]);
> $critvulns_worksheet->write($critvulns_ctr, 4, $tmp[2]);
> $critvulns_worksheet->write($critvulns_ctr, 5, $tmp[6]);
> $critvulns_worksheet->write($critvulns_ctr, 6, $tmp[7]);
> $critvulns_worksheet->write($critvulns_ctr, 7, $tmp[8]);
> $critvulns_worksheet->write($critvulns_ctr, 8, $tmp[9]);
> $critvulns_worksheet->write($critvulns_ctr, 9, $tmp[10]);
> ++$critvulns_ctr;
> }
> # end foreach (@critvuln)
>
1351c1421
# end foreach (@nonevuln)
1370,1378c1440,1449
write(1, 12, ‘Minimum password len’);
write(1, 13, ‘Password history len’);
write(1, 14, ‘Maximum password age days’);
write(1, 15, ‘Password must meet complexity requirements’);
write(1, 16, ‘Minimum password age days’);
write(1, 17, ‘Forced logoff time Seconds’);
write(1, 18, ‘Locked account time seconds’);
write(1, 19, ‘Time between failed logon seconds’);
write(1, 20, ‘Number of invalid logon before locked out seconds’);
—
> $HostConfigData_worksheet->write(1, 12, ‘Severity Critical (4)’);
> $HostConfigData_worksheet->write(1, 13, ‘Minimum password len’);
> $HostConfigData_worksheet->write(1, 14, ‘Password history len’);
> $HostConfigData_worksheet->write(1, 15, ‘Maximum password age days’);
> $HostConfigData_worksheet->write(1, 16, ‘Password must meet complexity requirements’);
> $HostConfigData_worksheet->write(1, 17, ‘Minimum password age days’);
> $HostConfigData_worksheet->write(1, 18, ‘Forced logoff time Seconds’);
> $HostConfigData_worksheet->write(1, 19, ‘Locked account time seconds’);
> $HostConfigData_worksheet->write(1, 20, ‘Time between failed logon seconds’);
> $HostConfigData_worksheet->write(1, 21, ‘Number of invalid logon before locked out seconds’);
1396a1468
> $HostConfigData_worksheet->write($HostConfigData_ctr, 11, $host->{vuln_cnt}->{sev4});
1944c2016
merge_range( 1, 0, 1, 3, ‘User Account Sumamry’, $center_border6_format );
—
> $SummaryReport_worksheet->merge_range( 1, 0, 1, 3, ‘User Account Summary’, $center_border6_format );
2015a2088,2111
> $SummaryReport_worksheet->merge_range( $SummaryReport_cnt,0, $SummaryReport_cnt, 3, ‘Critical Severity Vulnerability Top 10 By Plugin Family’, $center_border6_format );
> ++$SummaryReport_cnt;
> $SummaryReport_worksheet->write($SummaryReport_cnt, 0, ‘plugin Family’);
> $SummaryReport_worksheet->write($SummaryReport_cnt, 1, ‘plugin id’);
> $SummaryReport_worksheet->write($SummaryReport_cnt, 2, ‘plugin Name’);
> $SummaryReport_worksheet->write($SummaryReport_cnt, 3, ‘count’);
> $SummaryReport_worksheet->set_column(‘A:M’, 20);
> ++$SummaryReport_cnt;
>
> my @critvuln_uniq_plugin_family = vuln_seperate_by_plugin(\@critvuln);
> foreach my $entry (@critvuln_uniq_plugin_family)
> {
> my @tmp = @{$entry->{entries}};
> foreach my $t (@tmp)
> {
> $SummaryReport_worksheet->write($SummaryReport_cnt, 0, $t->[5]);
> $SummaryReport_worksheet->write($SummaryReport_cnt, 1, $t->[0]);
> $SummaryReport_worksheet->write($SummaryReport_cnt, 2, $t->[3]);
> $SummaryReport_worksheet->write($SummaryReport_cnt, 3, $t->[2]);
> ++$SummaryReport_cnt;
> }
> }
>
> $SummaryReport_cnt = $SummaryReport_cnt + 3;
2117c2213
my @host_sum_array = (‘operating-system’,’local-checks-proto’,’name’,’sev0′,’sev1′,’sev2′,’sev3′,’sev4′,’Minimum password len’,’Password history len’,’Maximum password age (d)’,
2246,2247c2342,2343
< my $most_high_common_vuln = "";
my $most_crit_common_vuln = “”;
> if($critvuln[0] ne “”)
2250c2346
my $pivot_data = \@critvuln;
2259c2355
$most_crit_common_vuln = shift @t;
2261c2357
# end of if($critvuln[0] ne “”)
2263a2360
> my $total_crit = @critvuln;
2279a2377,2379
> $Home_worksheet->write($Home_cnt, 0, “Total Unique Critical Severity Vulnerability”);
> $Home_worksheet->write($Home_cnt, 1, $total_crit);
> ++$Home_cnt;
2293a2394,2397
> $total_crit = $total_crit+2;
> $Home_worksheet->write($Home_cnt, 0, “Total Count of Critical Severity Vulnerability”);
> $Home_worksheet->write($Home_cnt, 1, “\=SUM\(critvulns\!E3\:E$total_crit\)”);
> ++$Home_cnt;
2308,2309c2412,2413
write($Home_cnt, 0, “The most common high Severity vulnerability”);
write($Home_cnt, 1, $most_high_common_vuln->[3]);}
—
> $Home_worksheet->write($Home_cnt, 0, “The most common critical severity vulnerability”);
> if($most_crit_common_vuln){$Home_worksheet->write($Home_cnt, 1, $most_crit_common_vuln->[3]);}
2311c2415
write($Home_cnt, 0, “Number of System with a Informational(NONE-0) Severity Vulnerability”);
—
> $Home_worksheet->write($Home_cnt, 0, “Number of Systems with an Informational(0) Severity Vulnerability”);
2314c2418
write($Home_cnt, 0, “Number of System with a Low(1) Severity Vulnerability”);
—
> $Home_worksheet->write($Home_cnt, 0, “Number of Systems with a Low(1) Severity Vulnerability”);
2317c2421
write($Home_cnt, 0, “Number of System with a Medium(2) Severity Vulnerability”);
—
> $Home_worksheet->write($Home_cnt, 0, “Number of Systems with a Medium(2) Severity Vulnerability”);
2320c2424
write($Home_cnt, 0, “Number of System with a High(3) Severity Vulnerability”);
—
> $Home_worksheet->write($Home_cnt, 0, “Number of Systems with a High(3) Severity Vulnerability”);
2322a2427,2429
> $Home_worksheet->write($Home_cnt, 0, “Number of Systems with a Critical(4) Severity Vulnerability”);
> $Home_worksheet->write($Home_cnt, 1, “\=COUNTIF\(HostConfigData\!M3\:L$total_discovered_row\,\”\>0\”\)”);
> ++$Home_cnt;
Feature request – was going to do it myself but my Perl is rusty, at best: Would love to see a chart of vulnerabilities by severity by date. I have a directory with all my Nessus scans over the past few months, and I’d like to be able to have a trend chart. Seems like it should be easy enough (for someone who’s better with Perl than me) – grab the Scan Start Date attribute out of the plugin_output element and stick it in a hashmap by host and date.
all I get is “Invalid tag sequence: at parse_nessus_xml.v15.pl line 644. i tried going back to v14 also and that told me the same thing but instead at line 645… what should I do?
Great work on this tool, Tenable needs to have things like this built into Nessus. Can’t wait for the “Critical” vulnerabilities update though, manually separating them out for now.
Cody,
Had a few large reports and decided it would be faster to modify the perl script than pull the data manually for the CRITICAL Vulnerabilities. It is working great for me, I do not want to take any credit for the work you have done, so I am not linking to it. But if you shoot me a email I will respond with the script for you to review and do with as you please, I am sure it is not perfect.
I know how work gets in the way of the fun things so I thought I could help out and give a little back.
Do you mean the date the vulnerability was published?
@Karl
Karl, any chance you could point me in the direction of your modified script? would be greatly appreciated!
I am posting Karl’s script in a separate post, you can download it from there.
@Benjamin Blakely
How can I apply this patch? Also thanks for the great work.
When I run the script against individual files works well. When I point it to a folder tells me:
This file “XXXXXXXXXXXXXXX.nesses” is not using the Nessus version 2 format, and will NOT be parsed!!!
I am using Windows 7. Thanks in advance for any help you can offer.
The only thing I can think of that would cause that is if there are files in the folder that are not nessus file or if the “.” and “..”. but I filtered out the “.” and “..”. I have not tried to run the script on Windows 7 so there might be something I am missing there. I would do this, run script in a debugger and look at line 151 “my @files = readdir(DIR);” Look at the “@files” array, and you will see all the files that are present, then follow the script as I remove the “.” and “..”, then you will see what is left. One of those files is causing the issue. Next month I plan on working on a much needed update, and I will test the new version on windows 7 then.