[horde] Compromised account/Spammer detection hook

Kevin Konowalec webadmin at ualberta.ca
Tue Dec 16 19:30:48 UTC 2008


Hey guys,

Something we're constantly fighting with here is people falling prey  
to Phishing scams.  We're doing our best to educate our users but  
invariably someone will send their username and password to Nigeria  
and before you know it we're getting blocked by ISPs for sending  
spam.  Horde 3.3 helps a lot in this regard by allowing permissions to  
be set to limit the number of recipients a message can have and the  
number of messages that can be sent out during a specified time  
period.  However, where it was falling short for us was the lack of  
administrator notification when a user had hit that limit.  We want to  
be able to detect holed accounts as quickly as possible so we can  
disable and reset them without further damage being done.  Horde out  
of the box didn't have this functionality so I grabbed a PHP manual  
and wrote one myself.

I'm putting this out there to the community so that a) other admins  
can make use of it if they need something like this but also b)  
because I'm not a native PHP coder nor am I intimately familiar with  
the inner workings of the horde codebase so I'm hoping someone might  
spot something I missed or maybe suggest ways to make the code a  
little more elegant.

Anyway... this hook detects when a user exceeds the max_timelimit  
setting and then immediately grabs the contents of their (one or more)  
signatures (since that's where they usually hide the spam text) and  
packages it up into an email message to whatever your "problems" email  
is set up to be.  I also threw in a var dump of the 'confirm_email'  
field as I found a whole bunch of crap stuffed in there too so I just  
wanted to cover all the bases.

So here's the code.  Any comments/suggestions would be appreciated.

K



// Kevin's funky _perms_hook_denied function (/horde/config/hooks.php)

if (!function_exists('_perms_hook_denied')) {
     function _perms_hook_denied($permission)
     {

         if (($pos = strpos($permission, ':')) === false) {
             $app = $permission;
         } else {
             $app = substr($permission, 0, $pos);
             $perm = substr($permission, $pos+1, strlen($permission)- 
strlen($app)-1);
         }


         if ($app=="imp" && $perm=="max_timelimit") {

                 $user = Auth::getAuth();
                 $old_login = @unserialize($GLOBALS['prefs']- 
 >getValue('last_login'));
                 $lastlogin = sprintf("Last login: %s from %s",  
strftime('%c', $old_login['time']), $old_login['host']);
                 $timelimit = IMP::hasPermission('max_timelimit');

                 // Set up message body here

                 $ident = @unserialize($GLOBALS['prefs']- 
 >getValue('identities'));

                 foreach ($ident as $key => $val) {
                         $tmp = sprintf("Identity Sig %d -- (%s):\n\n%s 
\n\n",$key,$val['id'],$val['signature']);
                         $ident_dump = $ident_dump . $tmp;
                 }

                 $confirm = @unserialize($GLOBALS['prefs']- 
 >getValue('confirm_email'));
                 $confirm_dump = var_export($confirm,true);

                 $body = sprintf("We have detected a user that has  
exceeded the threshold for number of messages sent within a 24 hour  
period.\nThis could be a legitimate user se
nding a lot of mail, but it could also be a compromised account  
sending spam.\nMost of the time the spammers stuff the spam text into  
user signatures for their own convenience s
o that's the\nfirst place to look.\n\nThe account information follows  
below:\n\n\nUser ID:  %s\n%s\n\nIdentities Dump:\n================\n\n 
%s\n\nSometimes you get really weird
things going on with these guys stuffing spam text into\nthe  
confirmation email field.  If there's anything there it should appear  
below.\n\nConfirm_email dump:\n===============
===\n\n%s",$user, $lastlogin,$ident_dump,$confirm_dump);

                 require_once 'Horde/MIME/Mail.php';

                 $subject = "Message Limit Exceeded for user $user";
                 $email = $GLOBALS['conf']['problems']['email'];

                 $mail = new MIME_Mail(_("[Horde Spammer Alert]") . '  
' . $subject,
                         $body, $email, $email,
                          NLS::getCharset());
                 $mail->addHeader('Sender', 'horde-alert@' .  
$conf['problems']['maildomain']);

                 $mail_driver = $conf['mailer']['type'];
                 $mail_params = $conf['mailer']['params'];

                 $sent = $mail->send($mail_driver, $mail_params);

                 Horde::logMessage(
                     sprintf("%s Message sent to %s from %s",
                             $_SERVER['REMOTE_ADDR'],
                             preg_replace('/^.*<([^>]+)>.*$/', '$1',  
$email),
                             preg_replace('/^.*<([^>]+)>.*$/', '$1',  
$email)),
                     __FILE__, __LINE__, PEAR_LOG_INFO);

         }


         $message = @htmlspecialchars(sprintf(_("You are not allowed  
to send messages to more than %d recipients within %d hours.  This  
attempt has been logged and administrators
  notified."), $timelimit, $GLOBALS['conf']['sentmail']['params'] 
['limit_period']), ENT_COMPAT, NLS::getCharset());

         return $message;
     }
}



More information about the horde mailing list