[Snort-users] network penetrations

Geoff the UNIX guy galitz at ...247...
Fri Jan 12 01:13:16 EST 2001



For your viewing pleasure, the following perl code
hooks into a database of contacts (what groups or 
organization owns what machine and the releveant email
contact info) and also writes out a file of machines 
to scan after snort reports an event.

This is homebrew stuff, and I would be mightily obliged
for comments on cleaning it up or just plain doing
it better.  

If there is interest, I can come with a canned set of 
tables to supplement the snort database and some code
to automate the entire process of logging to notification
to follow-ip scanning.  Just let me know if you think
it would be useful to you.


-geoff



cut here
----------------------------------------------------------

#!/usr/bin/perl


###
#
#	eddie.pl
#	01/10/2001 galitz at ...247...
#
#	This perl script is meant as an example, though with
#	with a minimum of editing it can be adapted for use in
#	any environment
#
#	This script presumes you have two databases, the snort
#	database and a second database which contains records
#	of what IP addresses are owned by whom.  For example,
# 	here is an example table from our contact database:
#	
#+-----------+-------------+------+-----+---------+-------+
#| Field     | Type        | Null | Key | Default | Extra |
#+-----------+-------------+------+-----+---------+-------+
#| ip        | varchar(25) | YES  |     | NULL    |       |	IP address
#| CK        | varchar(25) | YES  |     | NULL    |       |	n/a
#| node      | varchar(25) | YES  |     | NULL    |       |	node name
#| cid       | varchar(25) | YES  |     | NULL    |       |	cable ID (not snort cid)
#| ctype     | varchar(25) | YES  |     | NULL    |       |	cable type
#| lastname  | varchar(25) | YES  |     | NULL    |       |	lastname of group owner
#| firstname | varchar(25) | YES  |     | NULL    |       |	firstname of group owner
#| building  | varchar(25) | YES  |     | NULL    |       |	building
#| room      | varchar(5)  | YES  |     | NULL    |       |	room
#| os        | varchar(25) | YES  |     | NULL    |       |	operating system
#| sysop     | varchar(25) | YES  |     | NULL    |       |	system administrator
#| contact   | varchar(25) | YES  |     | NULL    |       |	contact person for group
#| mac       | varchar(25) | YES  |     | NULL    |       |	n/a
#+-----------+-------------+------+-----+---------+-------+
#
#
#	Note that the code here presumes the user will access the
#	database without a password.  Therefore, when you create
#	the user to extract data from database, avoid giving that
#	user complete administrative access
#
#	That's it for now.  Feel free to send questions my way...
#	not that I can answer them, I'm no expert.
#
#	-galitz at ...247...



use DBI;		# required to interface to mysql
use Text::Wrap;		# optional, for formatting reports
use Mail::Mailer;	# required for email notification
use IO::Socket;		# required for the whois functionality




sub whoisit {

	# this function retreives the appropriate whois contact 
        # in a brute force approach.  This needs to be optimized

  my $domain = shift;
  $attempts = 0;
  $foundit = "false";

  while ($attempts <= 2) {
	my $addr;
	if ($attempts == 0) {
		$server = 'whois.arin.net';
	} elsif ($attempts == 1) {
		$server = 'whois.apnic.net';
	} elsif ($attempts == 2) {
		$server = 'whois.ripe.net';
	}
	my $scon = new IO::Socket::INET(PeerAddr => $server,
				  PeerPort => 'whois',
				  Proto => 'tcp');
	unless ($scon) {
		print "Couldn't connect to whois server. Sorry.\n";
		return;
	}
	$attempts = $attempts + 1;
	print $scon $domain, "\r\n";
	while (<$scon>) {
		if (/. at ...843.../) {
		   @duh = split (/\s+/,$_);	
		   $count = @duh;
		   $count = $count - 1 ;
		   $foundit = "true";
		}
	}
  }
  return $duh[$count];
}

# main segment


$Text::Wrap::columns = 80;  # set the report text format

# the line below gives us any events which have been logged within
# the past day or so.
my $GET_RECENT_HITS = "SELECT * FROM event WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)";

# the line below fills an array with IP addresses from the event
my $GETIP = "SELECT ip_src0, ip_src1, ip_src2, ip_src3, ip_dst0, ip_dst1, ip_dst2, ip_dst3 FROM iphdr WHERE cid = ?";

# information to use to connect to the database
my $DBTYPE = mysql;		# which DBI modules to load
my $DB1 = snort;		# which IDS sesnor database to use
my $DB1USER = CHANGE_ME;	# which user to extract sensor info from sensor database
my $DB2 = CHANGE_ME;		# your contact info will probably be in a seperate database and table
my $DB2USER = CHANGE_ME;	# user for the contact database
my $DNSTABLE = CHANGE_ME2;	# this is the table of ip addresses, node names, contacts
				# and so on...
my $GROUPNAME = lastname;	# this is how you you associate the group that owns the system
				# with the system info (e.g. IP address, OS and so on)


# SQL statement to get group owner of an IP address (see above)
my $GET_OWNER = "SELECT $GROUPNAME FROM $DNSTABLE WHERE ip = ?";

# SQL statement to get the contact person for that group
my $GET_CONTACT = "SELECT contact_email FROM owners WHERE owner = ?";

# local notification stuff
my $from_address = "unix\@nowhere.really"; 	# who the email notification should be from
my $subject = "IDS Event Notification";		# the subject line in the email notification


# the code below connects to a database, extracts whatever event it is told to 
# extract and builds the IP address of the local host, then retrieves the group
# owner and the contact person for that node.

# establish connection to database
my $dbh = DBI->connect("DBI:$DBTYPE:$DB1",$DB1USER) or die "Couldn't connect to database: " . DBI->errstr;

# prepare statement for execution
my $sth = $dbh->prepare($GET_RECENT_HITS) or die "Coudn't prepare statement: " . $dbh->errstr;
my @data;

# execute statement
$sth->execute or die "Couldn't execute statement: " . $sth-errstr;

# put together the bits from our query
while (@data = $sth->fetchrow_array()) {
	my $sid = $data[0];
	my $cid = $data[1];
	my $sig = $data[2];
	my $tstamp = $data[3];
	my $sth2 = $dbh->prepare($GETIP) or die "duh";

# retrieve the details of the event via the cid 
	$sth2->execute($cid);
	my @data2;
	#while (@data2  = $sth2->fetchrow_array()) {
	@data2 = $sth2->fetchrow_array();

# build the IP address from it's consituent parts
	my $SRCIP = "$data2[0].$data2[1].$data2[2].$data2[3]"; 
	my $DSTIP = "$data2[4].$data2[5].$data2[6].$data2[7]";

# establish a new connection to the database which contains
# details about your network and the nodes (including system owners)
	my $dbh2 = DBI->connect("DBI:$DBTYPE:$DB2",$DB2USER) or die "Couldn't connect to database: " . DBI->errstr;
        my $sth3 = $dbh2->prepare($GET_OWNER) or die "Coudn't prepare statement: " . $dbh2->errstr;	
        $sth3->execute($SRCIP) or die "Couldn't execute statement: " . $o-errstr;
        @owner = $sth3->fetchrow_array();
        my $own = $owner[0];	# this is the group that owns the node
        my $c = $dbh2->prepare($GET_CONTACT) or die "Coudn't prepare statement: " . $dbh2->errstr;
        $c->execute($own)  or die "Couldn't execute statement: " . $c-errstr;
        @emailaddr = $c->fetchrow_array();
        my $contact = @emailaddr[0];	# this is contact for that group

# *** note... you need to create this file or otherwise generate it on the fly ***
	open(NOTIFY, "generic.notification") || die "Can't open file $!\n";
       	my $body = <NOTIFY> or print "oops\n";

	open(SUSPECTS, "target.list") || die "Can't open file $!\n";
	print SUSPECTS "$DSTIP\n";
        # add checking to verify DSTIP is truly a local IP
	# SUSPECT is then used for nessus and nmap as targets to scan
	# when they are next invoked via cron (any easy way to prevent
        # stressing the server or network)

# this is the report that is sent to the screen or email via shell redirection
# for use as a report viewer as oppossed to the automatic notification

	$who = whoisit($SRCIP);
	print "IP Source Address = $SRCIP\n";
	print "IP Destination Address = $DSTIP\n";
	print "SRC Contact = $who\n";
	print "DATE = $tstamp\n";
	print "Group that owns node = $own\n";
	print "Local Contact = $contact\n";
	print "Signature = $sig\n";
	print "CID = $cid\n";
	print "Notification = $body\n";
	print "========================================\n";

# this is commented out during testing so folks don't get bogus emails.
# uncomment this to enable mail notification or override the settings
# with your own email address to see the notification before you put
# this into production

# this code makes automatic notification to local system owners
# something is going on.

#       $mailer = Mail::Mailer->new();
#       $mailer->open({ From    => $from_address,
#       To      => $contact,
#       Subject => $subject,
#       }) or die "Can't open: $!\n";
#       print $mailer $body;
#      $mailer->close();

# clean up our mess
		close (NOTIFY);
		close (SUSPECTS);
		$c->finish;
		$sth2->finish;
		$sth3->finish;
		$dbh2->disconnect;
}
$sth->finish;
$dbh->disconnect;





More information about the Snort-users mailing list