Re: Does snortsnarf work?
Ed Davison <[email protected]> Thu, 13 Feb 2003 11:54:01 -0600
| Newsgroups | gmane.comp.security.ids.snort.snarf |
|---|---|
| Message-ID | <[email protected]> |
--y0ulUmNC+osPPQO6 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, Feb 13, 2003 at 11:02:53AM -0600, Paul Schmehl wrote: > On Thu, 2003-02-13 at 10:48, James Hoagland wrote: > > > > Try running it from the command line and observe its memory and CPU > > use. If these increase, it is working on processing alerts. If > > there are alot of alerts to process, SnortSnarf can take a while. > > But it should eventually complete successfully. > > I've done it from the commandline. Just trying to process one day from > the database takes at least two hours, and memory consumption > continually increases until it's reached the limit. (I'm using a 1.3 > GHz processor/1GB RAM FreeBSD box.) I even ran it through cron last > night. No errors - no output. > > One time when I ran it, I saw some warning messages about uninitialized > values (coming from a perl module), but those aren't fatal, so they > shouldn't keep it from finishing. > > I'll try it again today and see if I can take a smaller sample. > I do not know how much difference it will make or even what version of the SnortDBInput.pm code you are running but I have made some changes that I have been meaning to post to James Hoagland for inclusion in the newer versions of the code. I am going to attach it here and make sure that it is on my website so that it is now publicly available. Work has been done to switch it to a more compatible DBI codebase and there has been some speedup code added. The speed of the queries is a big deal but have never seen NO output from the code. I will see what I can do to help with this as well. Ed Davison --y0ulUmNC+osPPQO6 Content-Type: application/x-perl Content-Disposition: attachment; filename="SnortDBInput.pm" Content-Transfer-Encoding: quoted-printable #!/usr/bin/perl =0A=0A# The SnortDBInput v.2=0A# original author Ed Davison= [[email protected]]=0A# modified by Aaron DeLashmutt [awd@awdonlin= e.com]=0A=0A# SnortDBInput is an implentation of the SnortSnarf Input API w= hich reads=0A# its input from databases produced by Snort using the databas= e output plugin.=0A# Currently SnortDBInput is capable of accessing MySQL a= nd Oracle through the=0A# DBI/DBD perl interface modules.=0A# http://search= .cpan.org/author/TIMB/DBI-1.30/DBI.pm=0A# http://search.cpan.org/author/TIM= B/DBD-Oracle-1.12/Oracle.pm=0A# http://search.cpan.org/author/JWIED/Msql-My= sql-modules-1.2219/mysql/lib/DBD/mysql.pm=0A=0A# To use SnortDBInput, pass = database information to SnortSnarf in the format=0A# user:password@database= @host:port=0A# EX : snortsnarf.pl snort:@[email protected]=0A=0A# Please send= complaints, kudos, and especially =0A# improvements and bugfixes to awd@aw= donline.com =0A=0A# -SnortSnarf-=0A# copyright (c) 2001 by Silicon Defense = (http://www.silicondefense.com/)=0A# Released under GNU General Public Lice= nse, see the COPYING file included=0A# with the distribution or http://www.= silicondefense.com/software/snortsnarf/=0A# for details.=0A=0A=0Apackage Sn= ortDBInput;=0A=0Ause MemAlert;=0Ause MemPacket;=0Ause Filter;=0Ause DBI;=0A= use Socket;=0Ause Time::ParseDate;=0A=0Asub BEGIN {=0A @cap_tasks=3D qw(= snort spp_portscan spade);=0A %cap_tasks=3D ();=0A foreach (@cap_task= s) {=0A $cap_tasks{$_}=3D 1;=0A }=0A}=0A=0Asub ref_to_url {=0A = my($cite,$id)=3D @_;=0A return undef unless defined($cite) && defined($= id);=0A if ($cite eq 'arachnids') {=0A $id =3D~ s/^0+//;=0A = return "http://whitehats.com\/IDS\/IDS$id";=0A } elsif ($cite eq 'bugt= raq') {=0A return "http://www.securityfocus.com/bid/$id";=0A } el= sif ($cite eq 'cve') {=0A return "http://cve.mitre.org/cgi-bin/cvena= me.cgi?name=3D$id";=0A } elsif ($cite eq 'mcafee') {=0A return "h= ttp://vil.nai.com/vil/dispVirus.asp?virus_k=3D$id";=0A } elsif ($cite eq= 'sid') {=0A return "http://www.snort.org/snort-db/sid.html?id=3D$id= ";=0A } elsif ($cite eq 'url') {=0A return "http://$id";=0A } = else {=0A return undef;=0A }=0A}=0A=0A########## API functions ##= ############=0A=0A# API 'new' function to create an instance=0Asub new {=0A= my($class,$paramsref,$tasksref,$filter,@inputs)=3D @_;=0A my(%tasks)= =3D ();=0A foreach (@{$tasksref}) {=0A $tasks{$_}=3D 1 if $_ eq '= all' || defined($cap_tasks{$_});=0A }=0A=0A my $dbmin =3D undef;=0A = my $dbmax =3D undef;=0A =0A my @filters=3D (ref($filter) eq 'AndFil= ter') ? @{$filter} : ($filter);=0A my @unhfilters=3D ();=0A foreach (= @filters) {=0A my $time=3D &Filter::known_mintime_filter($_);=0A = if (defined($time)) {=0A $dbmin=3D $time;=0A next= ;=0A }=0A $time=3D &Filter::known_maxtime_filter($_);=0A = if (defined($time)) {=0A $dbmax=3D $time;=0A next;= =0A }=0A push(@unhfilters,$_);=0A }=0A my $myfilter=3D = @unhfilters=0A ? (@unhfilters > 1=0A ? AndFilter->new(@un= hfilters)=0A : $unhfilters[0])=0A : TrueFilter->new();=0A= =0A my @ins=3D ();=0A # @inputs is the text list of databases to = grab stuff from, each in the form user:passwd@name@host:port=0A my($lhs,= $rhs,$user,$pass,$dbname,$hostport,$host,$port);=0A foreach (@inputs) {= =0A ($lhs,$rhs)=3D split('@',$_,2);=0A ($user,$pass)=3D split= (':',$lhs,2);=0A $pass=3D '' unless defined($pass);=0A ($lhs,= $rhs)=3D split('@',$rhs,2);=0A if (defined($rhs)) {=0A $d= bname=3D $lhs;=0A $hostport=3D $rhs;=0A } else {=0A = $dbname=3D 'snort'; =0A $hostport=3D $lhs;=0A }=0A = if ($hostport =3D~ /^(.*)\:(\d+)$/) {=0A $host=3D $1;=0A = $port=3D $2;=0A } else {=0A $host=3D $hostport= ;=0A # need to default to specific database port=0A }=0A = #encode the password by replacing ';' with \001; we assume \001 is not in t= he password string=0A $pass =3D~ tr/\;/\001/;=0A push(@ins,jo= in(';',$user,$pass,$dbname,$host,$port));=0A }=0A =0A my $self=3D = bless {=0A 'tasks' =3D> \%tasks, # requested tasks are the keys=0A = 'filter' =3D> $filter, # original filter=0A 'myfilter' =3D> $f= ilter, # filter to apply=0A 'str' =3D> undef, # recreate string=0A = 'inputsleft' =3D> \@ins, # databases not yet processed, each in the f= orm user;passwd;name;host;port=0A 'dbh' =3D> undef,=0A 'dbmin= ' =3D> $dbmin,=0A 'dbmax' =3D> $dbmax,=0A 'dbtext' =3D> '' # = for alert 'source' fields=0A }, $class;=0A=0A # get opts=0A my @pa= rams=3D ();=0A =0A # if at some point there is a general user specifi= ed option not tied to a particular =0A # input source (for example in Sn= ortFileInput the user can indicate how to infer an i=0A # alerts year), = e.g. 'foo', you would put that into the 'opts' hash with something like thi= s=0A# foreach (keys %$paramsref) {=0A# if (/^foo$/) {=0A# = $self->{'opt'}{$_}=3D $paramsref->{$_};=0A# } else {=0A# = warn "new: paramater $_ with value $paramsref->{$_} not understood, ign= oring\n";=0A# next;=0A# }=0A# push(@params,"$_:".$= paramsref->{$_});=0A# }=0A =0A # make the recreate string=0A my= $paramstr=3D &Filter::join_strs(@params);=0A $self->{'str'}=3D &Filter:= :join_strs(join(',',keys %tasks),&Filter::as_str($filter),$paramstr,@inputs= );=0A=0A # set up per opts=0A=0A # don't do much here, we don't even = know if get() is going to be called, maybe on recreate_str() is=0A=0A re= turn $self;=0A}=0A=0A=0Asub recreate {=0A my($class,$recreate_str)=3D @_= ;=0A my($tasks,$filterstr,$params,@inputs)=3D &Filter::unjoin_strs($recr= eate_str);=0A my @tasks=3D split(',',$tasks);=0A my $filter=3D &Filte= r::from_str($filterstr);=0A die "failed to recreate filter from string: = $filterstr\n" unless defined($filter);=0A my %params=3D map(split(':',$_= ,2),&Filter::unjoin_strs($params));=0A return $class->new(\%params,\@tas= ks,$filter,@inputs);=0A}=0A=0Asub recreate_str {=0A return $_[0]->{'str'= };=0A}=0A=0Asub task_capability {=0A return @cap_tasks;=0A}=0A=0Asub get= {=0A my $self=3D shift;=0A=0A# debug EBD=0A# print "* Entering get() ro= utine\n";=0A# my $a =3D `free | grep Mem`;=0A# print "* $a";=0A =0A m= y $got_an_alert=3D 0;=0A do {=0A # open a new input source unless= one is open (indicated by !defined($self->{'dbh'}))=0A while (!defi= ned($self->{'dbh'})) {=0A # need to move to a new input source= =0A my $curinput=3D $self->{'curinput'}=3D shift(@{$self->{'inpu= tsleft'}});=0A return undef if (!defined($curinput)); # ran out = of inputs; we're done!=0A =0A# log the new data source=0A# open = D, ">>.SnortDBInput.log";=0A# print D "------------------------------------= --\n";=0A# my $d =3D `date`;=0A# print D $d . "\n\n";=0A# print D "Starting= new DB data source: " . $curinput . "\n";=0A# print D "Filter specified: "= . $self->{'filter'} . "\n";=0A# close D;=0A=0A my ($user,$pwd,$= db,$host,$port)=3D split(';',$curinput);=0A $pwd =3D~ tr/\001/\;= /; # decode encoded password=0A $self->{'dbtext'}=3D "$user\@$db= \@$host:$port";=0A=0A# debug EBD=0A# print "* Connecting to $host as $user\= n";=0A=0A# this assumes an argument was passed with the default port=0A# sp= ecific to the database. =0A if ($port =3D=3D 3306) {=0A $dbtype =3D "mysql= ";=0A $dbh =3D DBI->connect("DBI:$dbtype:$db:$host:$port",$user, $pwd);=0A= } elsif ($port =3D=3D 1521) {=0A $dbtype =3D "Oracle"; =0A $dbh =3D DBI-= >connect("DBI:$dbtype:host=3D$host;sid=3D$db;port=3D$port", $user, $pwd);= =0A } elsif ($port =3D=3D 5432) {=0A $dbtype =3D "Pg"; =0A $dbh =3D DBI->= connect("DBI:$dbtype:host=3D$host;dbname=3D$db;port=3D$port", $user, $pwd);= =0A }=0A=0A if (!defined $dbh) {=0A warn "Error c= onnecting to $host as $user; skipping\n";=0A next;=0A = }=0A # got it open okay=0A $self->{'dbh'} =3D $d= bh;=0A =0A # possible todo: check to see if the datab= ase follows the expected schema=0A # if ($db_schema !=3D $our_sc= hema) {=0A # warn "$curinput has schema $db_schema, but we o= nly know $our_schema, we'll see how well this works";=0A # }=0A = =0A # get sth_event, num_rows, rowcount ready for cyc= ling through the database=0A=0A $q_event =3D "select sid, cid fr= om event";=0A my $whereClause=3D'';=0A# debug EBD=0Aprint "* Staring qu= ery: $q_event $whereClause\n";=0A if (defined($self->{'dbmin'}))= {=0A #if ($q_event =3D~ /where/) {=0A if ($w= hereClause =3D~ /where/) {=0A $whereClause .=3D " and "; =0A = } else { =0A $whereClause .=3D " where "; =0A }=0A# de= bug EBD=0Aprint "* Staring query: $q_event $whereClause\n";=0A# modify quer= y format specific to the database.=0A if ($dbtype eq "mysql") {=0A = $whereClause .=3D "unix_timestamp(timestamp) >=3D " . $s= elf->{'dbmin'};=0A } elsif ($dbtype eq "Oracle") {=0A $whereCl= ause .=3D "(to_char(timestamp,'J') -=0A to_char(to_date('01-JAN-19= 70','DD-MON-YYYY'),'J'))*86400 +=0A to_char(timestamp, 'SSSSS') >= =3D " . $self->{'dbmin'};=0A } elsif ($dbtype eq "Pg") {=0A $w= hereClause .=3D "(to_char(timestamp,'J') -=0A to_char(to_date('01-= JAN-1970','DD-MON-YYYY'),'J'))*86400 +=0A to_char(timestamp, 'SSSS= S') >=3D " . $self->{'dbmin'};=0A }=0A }=0A=0A# debug EB= D=0Aprint "* Staring query: $q_event $whereClause\n";=0A=0A if (= defined($self->{'dbmax'})) {=0A #if ($q_event =3D~ /where/) = {=0A if ($whereClause =3D~ /where/) {=0A = $whereClause .=3D " and ";=0A } else {=0A = $whereClause .=3D " where ";=0A }=0A=0A# debug EBD=0Aprin= t "* Staring query: $q_event $whereClause\n";=0A if ($dbtype eq "my= sql") {=0A #$q_event .=3D " unix_timestamp(timestamp) <=3D " . $se= lf->{'dbmax'};=0A $whereClause .=3D " unix_timestamp(timestamp) <= =3D " . $self->{'dbmax'};=0A } elsif ($dbtype eq "Oracle") {=0A = $whereClause .=3D "(to_char(timestamp,'J') -=0A = to_char(to_date('01-JAN-1970','DD-MON-YYYY'),'J'))*86400 +=0A = to_char(timestamp, 'SSSSS') >=3D " . $self->{'dbmax'};=0A } elsif ($= dbtype eq "Pg") {=0A $whereClause .=3D "(to_char(timesta= mp,'J') -=0A to_char(to_date('01-JAN-1970','DD-MON-YYYY= '),'J'))*86400 +=0A to_char(timestamp, 'SSSSS') >=3D " . $self->{'= dbmax'};=0A }=0A }=0A=0A# debug EBD=0Aprint "* Staring query: $= q_event $whereClause\n";=0A=0A $sth_event =3D $dbh->prepare("$q_event $= whereClause");=0A $sth_event->execute();=0A=0A# debug EBD=0A# pr= int "* Complete with query\n";=0A# my $a =3D `free | grep Mem`;=0A# print "= * $a";=0A# $state =3D "SELECT COUNT(*) FROM event $whereClause";=0A# $sth = =3D $dbh->prepare($state);=0A# $sth->execute();=0A# $total_rows =3D $sth->f= etchrow;=0A =0A# debug EBD=0A# print "Total rows: $total_rows\n";=0A= # open D, ">>.SnortDBInput.log";=0A# print D "Total rows in event table: " = . $total_rows . "\n";=0A# close D;=0A=0A $self->{'sth_event'} = =3D $sth_event;=0A $self->{'num_rows'} =3D $total_rows;=0A = $self->{'rowcount'} =3D 0;=0A } #end of do=0A=0A my $to= tal_rows =3D $self->{'num_rows'};=0A my $rowcount =3D $self->{'rowco= unt'};=0A my $sth_event =3D $self->{'sth_event'};=0A=0A# debug EBD= =0A# printf "* Current row =3D %d (%5.2f %%)\n", $rowcount, ($rowcount/$tot= al_rows);=0A =0A @query_results =3D $sth_event->fetchrow_array;=0A = $self->{'rowcount'} =3D $rowcount + 1;=0A =0A# debug EBD=0A# if ($= rowcount > 500000) {=0A# return undef;=0A# }=0A=0A# debug EBD=0A# if (!= ($rowcount % 50000)) {=0A# open D, ">>.SnortDBInput.log";=0A# print D "* = Current row:" . $rowcount . "\n";=0A# close D;=0A# }=0A=0A unless (= @query_results) { # ran out of events here=0A # clean up databas= e here=0A $self->{'sth_event'}=3D undef;=0A $self->{'= dbh'}=3D undef; # indicate that we need a new input source=0A } else= {=0A $alert =3D $self->make_alert($query_results[0],$query_resu= lts[1]);=0A if (defined $alert) {=0A# debug EBD=0A# print "* Ale= rt is valid\n";=0A# print "* Alert: ".$alert."\n";=0A# $alert->debug_print(= '* ',STDOUT);=0A $got_an_alert=3D=0A (d= efined($self->{'tasks'}{'all'})=0A || defined($self->{'t= asks'}{$alert->type()})) # make sure it matches one of our tasks=0A = && $self->{'myfilter'}->test($alert); # make sure it passes our= filter too=0A } else {=0A $got_an_alert =3D undef;= =0A }=0A unless ($got_an_alert) {=0A# debug EBD=0A# o= pen D, ">>.SnortDBInput.log";=0A# print D "* alert did not pass type test o= f the filter test\n";=0A# close D;=0A }=0A }=0A } unti= l ($got_an_alert);=0A=0A# debug EBD=0A# if (!defined $alert) {=0A# open D,= ">>.SnortDBInput.log";=0A# print D "* alert undefined\n";=0A# close D;= =0A# }=0A =0A return $alert;=0A}=0A=0A########## end of API funct= ions ##############=0A=0A=0A# if this parsed or unparsed alert is an anomal= y report, return the anomaly=0A# score otherwise return undef=0Asub is_anom= _rept {=0A my($alert)=3D shift;=0A my $text=3D ref($alert) ? $alert->= {'sig'} : $alert;=0A $text =3D " ";=0A if ($text =3D~ /(spp_anomsenso= r|Spade):\s*Anom[ao]ly threshold exceeded:\s*(\d+\.\d+)/i) {=0A retu= rn $2;=0A } else {=0A return undef;=0A }=0A}=0A=0A# parses giv= en sid, cid in snort db into an instance of MemAlert=0Asub make_alert {=0A = my($self,$sid,$cid)=3D @_;=0A=0A# debug EBD=0A# print "** Entering make_= alert() routine\n";=0A=0A my $aid =3D "snortdb:".$sid.":".$cid;=0A my= $dbh =3D $self->{'dbh'};=0A=0A #some default values=0A my $src_port = =3D 0;=0A my $dst_port =3D 0;=0A=0A my $alert =3D MemAlert->new($aid)= ;=0A my $pkt =3D MemPacket->new();=0A $alert->add_packets($pkt);=0A = $alert->set('source' =3D> $self->{'dbtext'}.'-'."$sid:$cid");=0A=0A# debu= g EBD=0A# print "** Grabbing alert for cid =3D $cid and sid =3D $sid\n";=0A= my $q;=0A if ($dbtype eq "mysql") {=0A $q =3D "select * from eve= nt where cid =3D $cid and sid =3D $sid";=0A } elsif ($dbtype eq "Oracle"= ) {=0A $q =3D "select sid,cid,signature,to_char(timestamp, 'yyyy-mm-dd = hh24:mi:ss') =0A from event where cid =3D $cid and sid =3D $sid";=0A } = elsif ($dbtype eq "Pg") {=0A $q =3D "select sid,cid,signature,to_char(t= imestamp, 'yyyy-mm-dd hh24:mi:ss') =0A from event where cid =3D $cid and s= id =3D $sid";=0A }=0A $sth =3D $dbh->prepare($q);=0A $sth->execute= ();=0A my @event =3D $sth->fetchrow_array;=0A my ($datetext,$timetext= ) =3D split / /, $event[3];=0A my ($year,$month,$day) =3D split /-/, $da= tetext;=0A my $utime =3D Time::ParseDate::parsedate($event[3], 'FUZZY' = =3D> 1);=0A $alert->set('utime' =3D> $utime);=0A=0A# debug EBD=0A# open = D, ">>.TimeFilter.log";=0A# print D "** utime real: ".$utime." alert value:= ".$alert->utime()."\n";=0A# close D;=0A =0A# debug EBD=0A# print "S= ID: ".$event[0]."\n";=0A# print "CID: ".$event[1]."\n";=0A# print "Date: ".= $datetext."\n";=0A# print "Time: ".$timetext."\n";=0A=0A# debug EBD=0A# pri= nt "** Grabbing signature data for sig_id =3D $event[2]\n";=0A=0A $q =3D= "select * from signature where sig_id =3D $event[2]";=0A $sth =3D $dbh-= >prepare($q);=0A $sth->execute();=0A @signature =3D $sth->fetchrow_ar= ray;=0A my $sig_text =3D $signature[1];=0A my $priority =3D $signatur= e[3];=0A# look for snort signature reference (sid)=0A# add the reference to= the alert=0A if (defined($signature[5])) {=0A my $url=3D &ref_to_url('s= id',$signature[5]);=0A $alert->add_ref('sid',$signature[5],$url);=0A= }=0A=0A# additional code to look for other site references such=0A# as = arachnids, cve, bugtraq, etc=0A $q =3D "select reference.ref_tag, ref_sy= stem_name=0A from reference_system, sig_reference, reference, signature= =0A where signature.sig_id=3D$event[2] and=0A sig_reference.ref_id=3D= reference.ref_id and=0A signature.sig_id=3Dsig_reference.sig_id and=0A = reference.ref_system_id=3Dreference_system.ref_system_id";=0A $sth =3D= $dbh->prepare($q);=0A $sth->execute();=0A my @extranfo;=0A while = ((@extranfo) =3D $sth->fetchrow_array) {=0A if (defined($extranfo[1])) {=0A= my $url=3D &ref_to_url($extranfo[1],$extranfo[0]);=0A $alert->add_ref($e= xtranfo[1],$extranfo[0],$url);=0A }=0A }=0A =0A# debug EBD=0A#= print "** Signature: ".substr($sig_text,0,50)."\n";=0A=0A my $anom=3D &= is_anom_rept($sig_text);=0A if (defined($anom)) {=0A $pkt->set('a= nom' =3D> $anom);=0A $alert->set('type' =3D> 'spade');=0A } else = {=0A $pkt->set('anom' =3D> undef);=0A if ($sig_text =3D~ /spp= _portscan/) {=0A $alert->set('type' =3D> 'spp_portscan');=0A = return undef;=0A } else {=0A $alert->set('type' = =3D> 'snort');=0A }=0A }=0A=0A# debug EBD=0A# print "** Grabbing = iphdr info for cid =3D $cid and sid =3D $sid\n";=0A=0A $q =3D "select si= d,cid,ip_src,ip_dst,ip_ver,ip_hlen,ip_tos,ip_len,=0A ip_id,ip_flags,ip_of= f,ip_ttl,ip_proto,ip_csum from =0A iphdr where cid =3D $cid and sid =3D $= sid";=0A $sth =3D $dbh->prepare($q);=0A $sth->execute();=0A my @ip= hdr =3D $sth->fetchrow_array;=0A my $src_address =3D $iphdr[2];=0A my= $dst_address =3D $iphdr[3];=0A# convert the hex value ip address=0A# to de= cimal=0A my $convert =3D sprintf "%08lx", $src_address;=0A my $a =3D = hex (substr ($convert,0,2));=0A my $b =3D hex (substr ($convert,2,2));= =0A my $c =3D hex (substr ($convert,4,2));=0A my $d =3D hex (substr (= $convert,6,2));=0A $src_address =3D "$a\.$b\.$c\.$d";=0A $convert =3D= sprintf "%08lx", $dst_address;=0A $a =3D hex (substr ($convert,0,2));= =0A $b =3D hex (substr ($convert,2,2));=0A $c =3D hex (substr ($conve= rt,4,2));=0A $d =3D hex (substr ($convert,6,2));=0A $dst_address =3D = "$a\.$b\.$c\.$d";=0A=0A my $protocol =3D $iphdr[12];=0A my $ttlstuff = =3D "TTL:" . $iphdr[11] . " TOS:" . $iphdr[6] . " ID:" . $iphdr[8];=0A $= ttlstuff =3D $ttlstuff . " IpLen:" . $iphdr[5] . " DgmLen:" . $iphdr[7];=0A= =0A my $otheropts=3D '';=0A my $prototext=3D "PROT$protocol";=0A $= src_port=3D undef;=0A $dst_port=3D undef;=0A if ($protocol =3D=3D 1) = {=0A# ICMP protocol=0A# debug EBD=0A# print "** Grabbing icmphdr for cid = =3D $cid and sid =3D $sid\n";=0A=0A $q =3D "select * from icmphdr wh= ere cid =3D $cid and sid =3D $sid";=0A $sth =3D $dbh->prepare($q);= =0A $sth->execute();=0A my @icmphdr =3D $sth->fetchrow_array;= =0A $pkt->set('protocol' =3D> 'ICMP');=0A $prototext =3D "ICM= P";=0A # add code to decode icmp_type into string=0A $pkt->se= t('flags' =3D> $icmphdr[2]);=0A $otheropts =3D "Type:" . &numtext($i= cmphdr[2]) . " Code:" . &numtext($icmphdr[3]);=0A $otheropts =3D $ot= heropts . " ID:" . &numtext($icmphdr[5]) .=0A = " Seq:" . &numtext($icmphdr[6]);=0A } #end of ICMP protocol=0A=0A i= f ($protocol =3D=3D 6) {=0A# TCP protocol=0A# debug EBD=0A# print "** Grabb= ing tcphdr for cid =3D $cid and sid =3D $sid\n";=0A=0A $q =3D "selec= t * from tcphdr where cid =3D $cid and sid =3D $sid";=0A $sth =3D $d= bh->prepare($q);=0A $sth->execute();=0A my @tcphdr =3D $sth->= fetchrow_array;=0A $src_port =3D $tcphdr[2];=0A $dst_port =3D= $tcphdr[3];=0A $pkt->set('protocol' =3D> 'TCP');=0A $protote= xt =3D "TCP";=0A my $flags=3D &tcpflags_num_to_str($tcphdr[8]);=0A = $pkt->set('flags' =3D> $flags);=0A $otheropts =3D $flags . " S= eq:" . &numtext($tcphdr[4]) . " Ack:" . &numtext($tcphdr[5]);=0A $ot= heropts =3D $otheropts . " Win:" . &numtext($tcphdr[9]);=0A } #end of TC= P protocol=0A =0A if ($protocol =3D=3D 17) {=0A# UDP protocol=0A# deb= ug EBD=0A# print "** Grabbing udphdr for cid =3D $cid and sid =3D $sid\n";= =0A=0A $q =3D "select * from udphdr where cid =3D $cid and sid =3D $= sid";=0A $sth =3D $dbh->prepare($q);=0A $sth->execute();=0A = my @udphdr =3D $sth->fetchrow_array;=0A $src_port =3D $udphdr[= 2];=0A $dst_port =3D $udphdr[3];=0A $pkt->set('protocol' =3D>= 'UDP');=0A $prototext =3D "UDP";=0A $otheropts =3D "";=0A = } #end of UDP protocol=0A=0A if (defined($signature[2])) {=0A# debug EB= D=0A# print "** Grabbing sig_class for sig_class_id =3D $signature[2]\n";= =0A=0A $q =3D "select * from sig_class where sig_class_id =3D $signa= ture[2]";=0A $sth =3D $dbh->prepare($q);=0A $sth->execute();= =0A my @classinfo =3D $sth->fetchrow_array;=0A my $classifica= tion =3D $classinfo[1];=0A $alert->set('classification_text' =3D> $c= lassification);=0A }=0A=0A $alert->set('message' =3D> $sig_text);=0A = $alert->set('priority_num' =3D> $priority);=0A $pkt->set('sip' =3D> $= src_address, 'dip' =3D> $dst_address, =0A 'sport' =3D> $src_port, 'd= port' =3D> $dst_port,=0A 'month' =3D> $month, 'day' =3D> $day, 'tod_= text' =3D> $timetext,=0A 'year' =3D> $year=0A );=0A =0A my = $alert_text =3D "[**] $sig_text [**]\n";=0A #push (@ptext, "[**] $sig_te= xt [**]");=0A my $pkt_text =3D "$datetext:$timetext ";#[smac] -> [dmac] = type:[val] len:[val]\n";=0A #push (@ptext, "$datetext:$timetext [smac] -= > [dmac] type:[val] len:[val]");=0A $pkt_text =3D $pkt_text . "$src_addr= ess";=0A $pkt_text =3D $pkt_text . ":$src_port" if defined($src_port);= =0A $pkt_text =3D $pkt_text . " -> $dst_address";=0A $pkt_text =3D $p= kt_text . ":$dst_port" if defined($src_port);=0A $pkt_text =3D $pkt_text= . "\n";=0A #push (@ptext, "$src_address:$src_port -> $dst_address:$dst_= port ");=0A $pkt_text =3D $pkt_text . $prototext . " " . $ttlstuff;=0A = #push (@ptext, $prototext . " " . $ttlstuff);=0A $pkt_text =3D $pkt_te= xt . "\n" . $otheropts if length($otheropts);=0A #push (@ptext, $otherop= ts);=0A $alert_text.=3D $pkt_text;=0A# print "got: $alert_text\n";=0A = =0A $pkt->set('text' =3D> $pkt_text, 'text_format' =3D> 'snortdb-full-p= kt');=0A $alert->set('text' =3D> $alert_text, 'text_format' =3D> 'snortd= b-full-alert');=0A # $pkt->set('as_text' =3D> @ptext);=0A # $alert->s= et('text_format' =3D> $pkt_text);=0A =0A# $alert->add_packets($pkt);= =0A=0A# debug EBD=0A# print "** Leaving make_alert() routine\n";=0A=0A r= eturn($alert);=0A}=0A=0Asub tcpflags_num_to_str {=0A my $flagnum=3D shif= t;=0A return '' unless defined($flagnum);=0A my $str=3D '';=0A $st= r.=3D ($flagnum & 0x80) ? '1' : '*';=0A $str.=3D ($flagnum & 0x40) ? '2'= : '*';=0A $str.=3D ($flagnum & 0x20) ? 'U' : '*';=0A $str.=3D ($flag= num & 0x10) ? 'A' : '*';=0A $str.=3D ($flagnum & 0x08) ? 'P' : '*';=0A = $str.=3D ($flagnum & 0x04) ? 'R' : '*';=0A $str.=3D ($flagnum & 0x02) = ? 'S' : '*';=0A $str.=3D ($flagnum & 0x01) ? 'F' : '*';=0A return $st= r;=0A}=0A=0Asub numtext {=0A my $num=3D shift;=0A return $num if defi= ned($num);=0A return '';=0A}=0A=0A1;=0A --y0ulUmNC+osPPQO6--