#! /usr/bin/perl # # simple attack detection using Yamaha RT logs # $Id: attack-detect.pl,v 1.4 1999/01/29 03:34:51 itojun Exp $ # $subnet = '210.160.95.96'; $bcast = '210.160.95.111'; $web = '210.160.95.104'; #$okay = '203.178.141.(19[2-9]|2[01][0-9]|22[0-4])'; $okay = ''; $logfile = "/var/log/entry.log.0.gz"; $timeoffset = 24 * 60 * 60; # one day $hostname = `/bin/hostname`; $hostname =~ s/\n$//; $ENV{'PATH'} = '/bin:/usr/bin:/sbin:/usr/sbin'; if (scalar(@ARGV) == 1) { $file = $ARGV[0]; $mailit = 0; } else { $t = (stat($logfile))[9]; if ($t < time - $timeoffset) { exit 0; } $file = $logfile; $mailit = 1; } if (! -f $file) { print STDERR "$file: no such file\n"; exit 1; } if ($file =~ /\.(z|Z|gz)$/) { open(IN, "gunzip -c < $file |") || die; } else { open(IN, "< $file") || die; } $starttime = $endtime = ''; while () { if ($starttime eq '') { $starttime = join(' ', (split(' ', $_))[0..2]); } $endtime = join(' ', (split(' ', $_))[0..2]); next if (!/Reject/); if (/filter: (TCP|UDP)/) { $checked = 0; ($sh, $sp, $dh, $dp) = /(\d+\.\d+\.\d+\.\d+):(\d+) > (\d+\.\d+\.\d+\.\d+):(\d+)/; $shstat{$sh}++; $spstat{$sp}++; $dhstat{$dh}++; $dpstat{$dp}++; $sstat{"$sh:$sp"}++; $dstat{"$dh:$dp"}++; if ($sh =~ /^(10|192\.168|172\.(1[6-9]|2[0-9]|3[01]))\./) { $privatesrc{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($sp == 0) { $port0src{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($sp == 65535) { $port65535src{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 0) { $port0dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 65535) { $port65535dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 111) { $port111dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 113) { $port113dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 119) { $port119dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if (137 <= $dp && $dp <= 139) { $port137dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 143) { $port143dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 513) { $port513dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 1080) { $port1080dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 2009) { $port2009dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dp == 2049) { $port2049dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if (6000 <= $dp && $dp <= 6063) { $port6000dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if (6000 <= $sp && $sp <= 6063) { $port6000src{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if (8000 <= $dp && $dp < 9100 && ($dp - 8000) % 8 == 0) { $port8000dst{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dh =~ /$bcast/) { $towardbcast{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } if ($dh =~ /$subnet/) { $towardsubnet{"$sh:$sp"} .= "$dh:$dp\n"; $checked++; } # special hack should be placed here if ($sh eq '210.160.95.100' && "$dh:$dp" eq '192.168.2.8:53') { $checked++; } if ($sh =~ /$okay/) { $checked++; } if (!$checked) { $unfiled{"$sh:$sp"} .= "$dh:$dp\n"; } } else { $unfiled .= "\t$_"; } } close(IN); if ($mailit) { open(OUT, "| /usr/sbin/sendmail -f root\@$hostname root\@$hostname") || die; select(OUT); print OUT "Subject: router attack summary\n"; print OUT "To: root\@$hostname\n"; print OUT "\n"; } print "$starttime - $endtime\n"; print "\n"; &report("source addr is private", %privatesrc); &report("source port is 0", %port0src); &report("source port is 65535", %port65535src); &report("source port is x11(6000-6063)", %port6000src); &report("dest port is 0", %port0dst); &report("dest port is 65535", %port65535dst); &report("dest port is sunrpc(111)", %port111dst); &report("dest port is ident(113)", %port113dst); &report("dest port is nntp(119)", %port119dst); &report("dest port is netbios-ns(137-139)", %port137dst); &report("dest port is imap(143)", %port143dst); &report("dest port is login(513)", %port513dst); &report("dest port is socks(1080)", %port1080dst); &report("dest port is news(2009)", %port2009dst); &report("dest port is nfsd(2049)", %port2049dst); &report("dest port is x11(6000-6063)", %port6000dst); &report("dest port is web proxies(8000 and others)", %port8000dst); &report("broadcast destination", %towardbcast); &report("subnet-addr destination", %towardsubnet); &statreport("source address", 10, %shstat); &statreport("dest address", 10, %dhstat); &statreport("dest port", 10, %dpstat); &statreport("source", 10, %sstat); &statreport("dest", 10, %dstat); &report("unfiled", %unfiled); exit 0; sub report { local($title, %values) = @_; local($i, $j, $t); local($in, $jn); local(%o) = (); $t = join('', values %values); $t =~ s/[^\n]//g; $t = length($t); return if ($t == 0); print "$title ($t times)\n"; foreach $i (keys %values) { $t = $values{$i}; %o = (); foreach $j (split(/\n/, $t)) { $o{$j}++; } foreach $j (keys %o) { $in = &getname($i); $jn = &getname($j); # print "\t$in\n\t\t-> $jn"; print "\t$in -> $jn"; if ($o{$j} != 1) { print " ($o{$j} times)\n"; } else { print "\n"; } } } print "\n"; } sub statreport { local($title, $top, %stat) = @_; local($i, $jn); if (0 < $top){ $title = "top $top $title"; } print "$title\n"; $i = 0; foreach $j (sort {$stat{$b} <=> $stat{$a}} keys %stat) { $jn = &getname($j); print "\t$stat{$j}\t$jn\n"; $i++; last if (0 < $top && $top < $i); } print "\n"; } sub getname { local($target) = @_; local($addr, $name); $addr = $target; if ($addr =~ /:\d+$/) { $addr =~ s/:\d+$//; } return $target if ($addr !~ /^\d+\.\d+\.\d+\.\d+$/); $addr = pack('C4', split(/\./, $target)); ($name) = gethostbyaddr($addr, 2); if ($name eq '') { return $target; } else { return "$target($name)"; } }