#!/usr/bin/perl
#####
#
# Copyright (C) 2005 Alexis CAURETTE  <alexis.caurette@gmail.com>
# All Rights Reserved
#
# This file is part of the Prelude program.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
#
#####

##
# This program est based on a fist proof of consept developped by
# Laurent Oudot whose release can be found on
# http://www.rstack.org/oudot/prelude/
#
# The latest Realease of this program can be found on
# http://www.linuxgateway.org
##

use DBI;
use Getopt::Long;

$count_treated=0;
$count_found=0;

my $db_type="";
my $db_name="";
my $db_host="";
my $db_user="";
my $db_password="";

my $file_config="";

my $verbose=0;
my $interactive=0; #not yet implemented
my $print_help=0;
my $print_version=0;

my $mode="one"; # big || one

my $tiny_version = "v0.2";
my $version="\n
This is the Nessus Alert Enforcer, $tiny_version 

Copyright 2005, Alexis CAURETTE <alexis.caurette\@gmail.com>
\n";

my $alertid;	#specific alert id on which we want to work to find correlation

my $usage="\nPrelude Correlation Vulnerability Finder, $tiny_version
Copyright 2002, Laurent Oudot

This tool can find correlation between the alerts stocked in your database, and the vulnerability reports that have been imported before in this database owing to the other associated tool. Those vulnerability reports must have been created owing to assessment tools (audits).  
Audit tools supported : Nessus (http://www.nessus.org)

$0	-c <vuln.conf>   --config <vuln.conf>
	[-v] [--verbose]
	[-h] [--help]
	[--version]
Example: $0 -c /usr/local/etc/prelude-correlation/vuln.conf

You Should redirect the outpu to a file you monitor with prelude-lml

The vuln.conf should just contain one line like this \"dbType:dbName:dbHost:dbUser:dbPassword:\"
Example of vuln.conf file content:   mysql:prelude:localhost:prelude:guessme:
\n";

## Main
#
args();
conf();
db();
correlation_alex();
#result();

sub args
{
	unless (GetOptions(
	"a|alertid=s"	=> \$alertid,
	"c|config=s"	=> \$file_config,
	"h|help"	=> \$print_help,
	"version"	=> \$print_version,
	"v|verbose"	=> \$verbose,
	))
	{
		die "$usage";
	};
	if( $print_help )
	{
		die "$usage";
	}
	if( $prinf_version )
	{
		die "$version";
	}
	if( ! $file_config )
	{
		die "$usage";
	}
}

## Read the configuration
#
sub conf
{
	open(CONF, $file_config) || die "Can't open the configuration file: $file_config: $!\n";
	while( <CONF> )
	{
		($db_type,$db_name,$db_host,$db_user,$db_password) = split(/\:/);
	}
	close(CONF);
}

## Connection to the database
#
sub db
{
#	print "*** Trying to connect to the database\n type:$db_type\t database:$db_name\n hostname:$db_host\t account:$db_user\n";
	if($verbose)
	{
#		printf " password:$db_password\n";
	}
	$db = DBI->connect("DBI:$db_type:database=$db_name:host=$db_host","$db_user","$db_password") || die "Cannot connect to the database: $!\n";
}


## Parse the database to match the alerts on which we gonna work
#

## Search correlation through vulnerability reports that have been inserted
#  in the prelude database
#
sub correlation_alex
{
	my $cve;
	if( $_[0] )
        {
                $cve=$_[0];
        }
	$reqcve= $db->prepare("select origin, name, address from Prelude_CorrelationVulnerability order by name");
	$reqcve->execute() or die "problem on select";
	while ($rowcve=$reqcve->fetchrow_arrayref)
	{
		$origin=$rowcve->[0];
		$name=$rowcve->[1];
		$address=$rowcve->[2];
		correlation_vulnerability($origin,$name,$address);
		#print "$origin $name Found\n";
	}
	$reqcve->finish;
	#print "Tous les CVE Identifies\n";
}
sub correlation_vulnerability
{
	my $origin;
	my $name;
	my $address;
	if( $_[0] )
	{
		$origin=$_[0];
	}
	if( $_[1] )
	{
		$name=$_[1];
	}
	if( $_[2] )
	{
		$address=$_[2];
	}
	#$reqid = db->prepare("select distinct _message_ident from Prelude_Reference where name = '$name'"); 
	$reqid = db->prepare("select distinct a._message_ident, a.address from Prelude_Reference as r, Prelude_Address as a where a._message_ident=r._message_ident and r.name = '$name' and a.address = '$address' and a._parent_type='T'");
	$reqid->execute() or die "Problem on select";
	while ($rowid=$reqid->fetchrow_arrayref)
	{
		$id=$rowid->[0];
		$ip=$rowid->[1];		
		#print "ID $id with IP $ip for $origin $name Found\n";
		generate_alert($origin,$name,$ip,$id);
	}
	$reqid->finish;
	#print "Tous les ID Traites\n";
}

sub generate_alert
{
	my $origin;
	my $name;
	my $address;
	my $ident;
	my $enforced;
	if ( $_[3] )
	{
		$origin=$_[0];
		$name=$_[1];
		$address=$_[2];
		$ident=$_[3];
	}
	$enforced=0;
	#print "Ident vaut $ident\n";
	#print "cve vaut $cve\n";
	#print "ip vaut $address\n";
	$reqcheck= db->prepare("select _ident from Prelude_CorrelationValidated where _ident='$ident'");
	$reqcheck->execute() or die "Problem on select";
	while($row=$reqcheck->fetchrow_arrayref)
	{
		if ($row->[0]==$ident)
		{
			#print "ID $ident deja enforce\n";
			$enforced=1;
		}
	}
#	print "Enforced vaut $enforced\n";
	if ($enforced==0)
	{	
		$reqdetails = db->prepare("select text from Prelude_Classification where _message_ident=$ident");
		$reqdetails->execute() or die "Problem on select";
		while ($rowdetails=$reqdetails->fetchrow_arrayref)
		{
			if (!($rowdetails->[0] =~ /(ALERTE AVEREE|DROPPED)/))
			{
				$reqsourcePort=db->prepare("select port from Prelude_Service where _message_ident='$ident' and _parent_type='S'");
				$reqdestPort=db->prepare("select port from Prelude_Service where _message_ident='$ident' and _parent_type='T'");
				$reqsourceIP=db->prepare("select address from Prelude_Address where _message_ident='$ident' and _parent_type='S'");
				$reqsourcePort->execute() or die "error running select";
				$reqsourceIP->execute() or die "error running select";
				$reqdestPort->execute() or die "error running select";
				$tmp=$reqsourcePort->fetchrow_arrayref;
				$sourceport=$tmp->[0];
				$tmp=$reqdestPort->fetchrow_arrayref;
				$destPort=$tmp->[0];
				$tmp=$reqsourceIP->fetchrow_arrayref;
				$sourceIP=$tmp->[0];
				@months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
				@weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
				($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
				$year = 1900 + $yearOffset;
				if ($hour < 10) {$hour = "0".$hour;}
				if ($minute < 10){ $minute = "0".$minute;}
				if ($second < 10) {$second = "0".$second;}
				if ($dayOfMonth < 10) {$dayOfMonth = "0".$dayOfMonth;}
				$date = "$months[$month] $dayOfMonth $hour:$minute:$second";
				print "$date localhost Nessus Enforcement for '$rowdetails->[0]' PreludeId=$ident $origin=$name Source=$sourceIP:$sourceport Destination=$address:$destPort\n";
				$count_found++;
			}
		}
		$reqvalidate = db->prepare("insert into Prelude_CorrelationValidated (_ident) values ('$ident')");
		$reqvalidate->execute() or die "Proble on Insert";
	
	}
}

# Print results
sub result
{
	#print "*** Operation of vulnerability correlation search finnished\n\n";
			@months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
			@weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
			($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
			$year = 1900 + $yearOffset;
			if ($hour < 10) {$hour = "0".$hour;}
			if ($minute < 10){ $minute = "0".$minute;}
			if ($second < 10) {$second = "0".$second;}
			if ($dayOfMonth < 10) {$dayOfMonth = "0".$dayOfMonth;}
			$date = "$months[$month] $dayOfMonth $hour:$minute:$second";
	print "$date localhost  Number of correlations of vulnerability  : $count_found\n";
}

