Full Disclosure mailing list archives

Re: Automated Vulnerability Scanners


From: Michael Holstein <michael.holstein () csuohio edu>
Date: Fri, 24 Feb 2006 16:13:10 -0500

Can anyone reccommend a perl based nessus wrapper that has the ability
to dump results into a mysql database?

Here is what I use. I wrote this a while ago (before I got better at Perl) .. feel free to criticize -- or improve upon -- this. It's got some debugging stuff in there commented out that I never removed. Be nice.

(If this wraps and gets ugly -- feel free to email offlist and I'll send as attachment).

If you want the database schema, I can send that too. I also have reporting scripts that generate nifty departmental emails to various people once a week telling them what to fix (also in perl).

Anyway ..

Here is how you run nessus, then involke this script :

/usr/local/nessus/bin/nessus -x -c myrcfile.rc -T nbe -q nessus_host 1241 nessus_user nessus_passwd ipinputfile outputfile.nbe

cat outputfile.nbe | nice -n 20 ./nessusimport.pl

This is pretty fast .. can process an entire test from a /16 and input the results into MySQL in about 5 minutes.

Cheers,

Michael Holstein CISSP GCIA
Cleveland State University

--snip--

#!/usr/local/bin/perl
use Net::SMTP;
use Date::Manip;
our $TZ = 'US/Eastern';
use DBI();

#####DATABASE PARAMETERS#####

$DATABASE="--dbname--";
$HOST="--hostname--";
$USERNAME="--username--";
$PASSWORD="--password--";

#connect to the database server
#DBI->trace(1, "trace.log"); #uncomment to log all DBI stuff
$dbh = DBI->connect("DBI:mysql:database=$DATABASE;host=$HOST", $USERNAME, $PASSWORD, {'RaiseError' => 1}) || die "Unable to connect: $dbh->errstr\n";


######MAIN PROGRAM LOOP######

while ( <STDIN> )
  {
        @results = split '\||\|\|';
        @results[6] =~ tr/;/\n/;
        @results[6] =~ tr/"/'/;
        @results[5] = "7";
        @results[5] = '1' if (@results[6] =~ "Risk factor : Critical");
        @results[5] = '1' if (@results[6] =~ "Risk factor : Serious");
        @results[5] = '1' if (@results[6] =~ "Risk factor : High");
        @results[5] = '2' if (@results[6] =~ "Risk factor : Medium");
        @results[5] = '2' if (@results[6] =~ "Risk factor : Medium/Low");
        @results[5] = '3' if (@results[6] =~ "Risk factor : Low/Medium");
        @results[5] = '3' if (@results[6] =~ "Risk factor : Low");
        @results[6] =~ s`Risk factor : Critical``;
        @results[6] =~ s`Risk factor : High``;
        @results[6] =~ s`Risk factor : Serious``;
        @results[6] =~ s`Risk factor : Medium``;
        @results[6] =~ s`Risk factor : Medium/Low``;
        @results[6] =~ s`Risk factor : Low/Medium``;
        @results[6] =~ s`Risk factor : Low``;
        for (@results[0]) { s/^\s+//;s/\s+$//; }
        for (@results[1]) { s/^\s+//;s/\s+$//; }
        for (@results[2]) { s/^\s+//;s/\s+$//; }
        for (@results[3]) { s/^\s+//;s/\s+$//; }
        for (@results[4]) { s/\<//g;s/^\s+//;s/\s+$//; }
        for (@results[5]) { s/^\s+//;s/\s+$//; }
        for (@results[6]) { s/^\s+//;s/\s+$//;s/\'/\\'/g;}
        my $ip = &dot2dec(@results[2]);
        next unless ($ip > 0);
        $timestamp = UnixDate(@results[4], '%Y-%m-%d %H:%M:%S');
        &findmainip($ip);

#condition 1 (entry is a timestamp for end of host scan)
if (@results[0] eq "timestamps" and @results[3] =~ 'host_end|host_start') {
                &updatemainip($ip,$timestamp);
#               print "Condition 1 Matched\n";
                }
#condition 2 (entry is a result record)
        if (@results[0] eq "results" and @results[5] < 7) {
                &findnessustimestamp($ip);

&updatenessus(@results[1],$ip,@results[3],@results[4],@results[5],@nessustime[1],@results[6]);

&updatestats(@results[1],$ip,@results[3],@results[4],@results[5],@nessustime[1]);
#               print "Condition 2 Matched\n";
                }
        else {
                next;
                }

}

#####GLOBAL SUBROUTINES#####

#turn dotted quad into decimal
sub dot2dec {
        my $address = @_[0];
        ($a, $b, $c, $d) = split '\.', $address;
        $decimal = $d + ($c * 256) + ($b * 256**2) + ($a * 256**3);
        return $decimal;
         }

#turn decimal into dotted
sub dec2dot {
        my $address = @_[0];
        $d = $address % 256; $address -= $d; $address /= 256;
        $c = $address % 256; $address -= $c; $address /= 256;
        $b = $address % 256; $address -= $b; $address /= 256;
        $a = $address;
        $dotted="$a.$b.$c.$d";
        return $dotted;
        }

#find IP in master table
sub findmainip {
my $query = $dbh->prepare("select idmain,mainip from ipmain where mainip = '@_[0]'"); $query->execute || die "Unable to locate IP in table ipmain: $dbh->errstr\n";
        @mainip = $query->fetchrow_array;
        return @mainip;
        }

#update/add IP&timestamp in master table
sub updatemainip {
my $query = $dbh->prepare("select * from ipmain where mainip=@_[0]"); $query->execute || die "Unable to locate IP in table ipmain: $dbh->errstr\n";
        @mainip = $query->fetchrow_array;
                if (@mainip[0]) {
$dbh->do("update ipmain set lastnessus='@_[1]' where idmain='@mainip[0]'") || die "problem with updatemainip 1:$dbh->errstr\n"; # print "updated values lastnessus=@_[1] where idmain=@mainip[0]\n";
                }
                else {
$dbh->do("insert into ipmain (mainip,lastnessus) values ('@_[0]','@_[1]')") || die "problem with updatemainip 2:$dbh->errstr\n";
#               print "inserted values mainip=@_[0], lastnessus=@_[1]\n";
                }
        return;
        }

#find last nessus timestamp for some IP
sub findnessustimestamp {
my $query = $dbh->prepare("select idmain,lastnessus from ipmain where mainip='@_[0]'") || die "problem with findnessustimestamp: $dbh->errstr\n"; $query->execute || die "Unable to locate nessus timestamp in table ipmain: $dbh->errsrt\n";
        @nessustime = $query->fetchrow_array;
        return @nessustime;
        }

#update/add nessus results records in nessusresults table
sub updatenessus {
my $query = $dbh->prepare("select * from nessusresults where nessushost='@_[1]' and scriptid='@_[3]'") || die "problem with updatenessus 1:$dbh->errstr\n"; $query->execute || die "Unable to locate record in NessusResults: $dbh->errstr\n";
        @nessus = $query->fetchrow_array;
                if (@nessus[0]) {
$dbh->do("update nessusresults set domain='@_[0]', nessushost='@_[1]', service='@_[2]', scriptid='@_[3]', risk='@_[4]', timestamp='@_[5]', msg='@_[6]' where idnessus='@nessus[0]'") || die "problem with updatenessus 2: $dbh->errstr\n"; # print "updated values domain=@_[0], host=@_[1], service=@_[2], script=@_[3], risk=@_[4], time=@_[5], msg=@_[6]\n";
                }
                else {
$dbh->do("insert into nessusresults (domain,nessushost,service,scriptid,risk,timestamp,msg) values ('@_[0]','@_[1]','@_[2]','@_[3]','@_[4]','@_[5]','@_[6]')") || die "problem with updatenessus 3: $dbh->errstr\n"; # print "inserted values domain=@_[0], host=@_[1], service=@_[2], script=@_[3], risk=@_[4], time=@_[5], msg=@_[6]\n";
                }
        return;
        }

sub updatestats {
$dbh->do("insert into nessusstats (domain,nessushost,service,scriptid,risk,timestamp) values ('@_[0]','@_[1]','@_[2]','@_[3]','@_[4]','@_[5]')") || die "problem with
updatestats 1: $dbh->errsrt\n";
# print "inserted stats values domain=@_[0], host=@_[1], service=@_[2], script=@_[3], risk=@_[4], time=@_[5]\n";
        return;
        }
_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/


Current thread: