Stopping Directory Harvest Attacks

Jeff A. Earickson jaearick at colby.edu
Tue Mar 28 23:33:16 IST 2006


Doesn't Julian's IPBlock feature kind of do the same thing???

Jeff Earickson
Colby College

On Mon, 27 Mar 2006, Brad Beckenhauer wrote:

> Date: Mon, 27 Mar 2006 22:08:49 -0600
> From: Brad Beckenhauer <Brad at beckenhauer.com>
> Reply-To: MailScanner discussion <mailscanner at lists.mailscanner.info>
> To: MailScanner discussion <mailscanner at lists.mailscanner.info>
> Subject: Stopping Directory Harvest Attacks
> 
> Hello all,
>
> First off my disclaimer...  I'm not a programmer and this script is one
> of my first perl writing ventures. A guys gotta start somewhere!  I was
> getting hammered with DHA (Directory Harvest Attacks) and decided to
> write my own.  Given that stopping DHA attacks has come up a couple of
> times on this forum, I hope that some of you will find this useful and
> a starting place to develop this script further.
>
> Julian,  I thought it would be cool to use some of your phishing logic
> to re-write the code to use a database instead.
>
> This perl script parses the mail.logs looking for multiple rejections
> from the same IP Address. Presume this is a Directory harvest Attack if
> the number of occurances of an IP Address is above the user defined
> limit of $SCORE, then create an iptables DROP statement for that IP
> Address.  Each time the script is run, it will remove the previous
> iptables entries, rescan the mail.log and add new entries.  If an IP
> offender no longer appears in the mail.log, then they are dropped off
> the blocked "list".  This works great a a cron job every hour and if you
> roll your mail logs daily the offending IP address is dropped off the
> list.
>
> Again, it's far from perfect, feel free to adapt it if you like it, but
> please share with the rest of us.
>
> #!/usr/bin/perl
> #
> # harvest.pl
> #
> # version 1.0
> # Date: 10 September 2005
> #
> # Find possible email "directory harvest attacks" from mail.logs
> #
> # Copyright:
> # This program is free software; you can redistribute it
> # and modify it under the terms of the GNU General Public
> # License as published by the Free Software Foundation.
> #
> # This program is distributed WITHOUT ANY WARRANTY; without even
> # the implied warranty of MERCHANTABILITY or FITNESS FOR A
> # PARTICULAR PURPOSE.
> #
> # Purpose:
> # Parses the mail.logs looking for multiple rejections from the same
> # IP Address. Presume this is a Directory harvest Attack if the
> # number of occurances of an IP Address is above the
> # user defined limit of $SCORE, then create an iptables DROP
> # statement for that IP Address.  Each time the script is run, it will
> # remove the previous iptables entries, rescan the mail.log and add
> # new entries.  If an IP offender no longer appears in the mail.log,
> # then they are dropped off the blocked "list".
> #
> # Rotating your email logs Daily helps keep the list cleaner.
> #
> # When executed, this perl script 'harvest.pl will create two output
> # files in the current directory:
> #
> # iptables.sh      Contains the iptables entires to be added to iptables
> # iptables-undo.sh Removes all entries created in the last run.
> #
> #
> #  Idea and initial code by: Brad Beckenhauer
> #
> #  Credits: David Kirby.
> #
> #
>
> # This is the threshhold for the number of times an
> # IP Address with a 550 error can occur in the mail logs before
> # being added to the block list.
> # SCORE should be set high enough that deleted user accounts
> # on your system do not "trigger" a false block.
> $SCORE=10;
>
> # Turn on console output, Shows what IP Addresses will be blocked.
> $DEBUG=1;
>
> # read input from the /var/log/mail.log file
> foreach $log (</var/log/mail.log >) {
>   open(FILE,$log);
>   while (<FILE>) {
>      chomp;    # Remove newlines
>      # create list of 55x errors
>      # 554 needs to be fixed to make sure that 'found' is numeric
>      if (/\]: 554 Service unavail/) { push @found, $_; }
>      # create list of 450 errors
>      if (/\]: 450 Client host rejected\</) { push @found, $_; }
>   }
>   close(FILE);
> }
>
> # parse list of 55x errors, extracting each IP
> foreach $entry (@found) {
>   ($ip)=$entry=~/.*\[.+?\].*\[(.*)\]/;
>   $iplist{$ip}++;   # count each IP found
> }
>
> # sort list of IPs ascending by number of occurances
> @iplist=sort { $iplist{$a} <=> $iplist{$b}; } (keys %iplist);
>
> # Print a report to console
> if ( $DEBUG ) {
>   printf "%-15s %-5s\n","\nIP Address"," Count";
>   printf "%-15s %-5s\n","---------------","-----";
> }
>
> open( OUT,  ">>/usr/local/sbin/dha.sh" );
> if ( \! -f "/usr/local/sbin/dha-undo.sh" ) {
>   print OUT "#!/bin/sh\n";
> }
> close(OUT);
>
> # if the undo file exists, do this routine
> if ( -f "/usr/local/sbin/dha-undo.sh" ){
> #   if ( $DEBUG ) { print " Undo file exists, reading it\n"; }
>   open(UNDO, "/usr/local/sbin/dha-undo.sh") || die " can't open
> iptables-undo.sh";
>   open(OUT, ">/usr/local/sbin/dha.sh") || die " can't open
> iptables.sh";
>
> # read in the undo file and send it to the OUT file
>   while ( <UNDO> ) {
>      # need to SKIP the first two lines of the input
>      # as they contain header
>      print OUT $_ ;
>   }
>   close(UNDO);
>   close(OUT);
> } else {
>   if ( $DEBUG ) { print "Undo file does not exist, creating\n"; }
> }
>
> # create a new BLANK file w/headers to "undo" the
> # new entries added to the table
> open( OUT, ">/usr/local/sbin/dha-undo.sh" );
> print OUT "#!/bin/sh\n";
> close(OUT);
>
> # open for append the iptables file for new IPs that exceed SCORE
> open( NEW,  ">>/usr/local/s/dha.sh" );
> open( UNDO, ">>/usr/local/sbin/dha-undo.sh" );
>
> # loop for each IP address found and add it to the tables.
> foreach $ip (@iplist) {
>  if ($iplist{$ip} >= $SCORE ) {
>     print NEW  "iptables -A INPUT -s $ip -p tcp -m tcp --dport 25 -j
> DROP\n";
>     print UNDO "iptables -D INPUT -s $ip -p tcp -m tcp --dport 25 -j
> DROP\n";
>     if ( $DEBUG ) { printf "%15s\t%5d\n",$ip,$iplist{$ip};  }
>  }
> }
>
> if ( $DEBUG ) {
>   printf "\nrun /usr/local/sbin/dha.sh to ADD these entries to the
> firewall\n";
>   printf "run /usr/local/sbin/dha-undo.sh to REMOVE all entries from
> the firewall\n\n";
> }
>
> close(NEW);
> close(UNDO);
> chmod 0755, '/usr/local/sbin/dha-undo.sh';
> chmod 0755, '/usr/local/sbin/dha.sh';
>
>
>
> -- 
> MailScanner mailing list
> mailscanner at lists.mailscanner.info
> http://lists.mailscanner.info/mailman/listinfo/mailscanner
>
> Before posting, read http://wiki.mailscanner.info/posting
>
> Support MailScanner development - buy the book off the website!
>


More information about the MailScanner mailing list