Friday, October 5, 2012

Monitor File Changes and Send Email Notification Script in PHP

Are you looking for a php program which will monitor a set of files and send email notifications in case of file size changes?

Just use this code, make it run once every hour or so (using crontab on Unix).

I wrote this to monitor sites' .htaccess files in case of hacking attack and alert me about it.

Please read the comments in the beginning - it is self explanatory. My private names/folders/password have been replaced with **** in this.

<?php /** * @file * This program will monitor changes in .htaccess files in hosting account. Urgent notification will be sent in case * of changes immediately. Also daily once( between 12-1 am) one DAILY notification will also be sent along with changes.txt file if present * else without this file. If you don't receive the email next day morning then immediately check for changes.txt and why you * did not get the notification may be because the program did not run. * If any file is missing then no email is sent but it is logged in changes.txt * * In the code below change the timezone in date_default_timezone_set to your area's * * Every time this runs, it moves the old *.sr file to *-old.sr * * BEFORE YOU MAKE CHANGES TO .HTACCESS(to prevent URGENT notification being generated) * - Check for changes.txt for any messages, delete it( if messages are of no use) * - delete *.sr file containing last history of file sizes (not recommended). If you don't delete it then one URGENT notification email * will be sent * * CHANGES.TXT * - All the information keeps on getting added to this file till you delete it * - Safely delete it only after carefully checking all the messages and that no URGENT messages are there. * * HOW IT WORKS * - Maintain a list of .httaccess to monitor; this can be got from: * -# cd your-home-directory * -# find . -name '.htaccess' -print //copy paste the output * - Change your home folder in the $home variable * - Put your email id(s) in $all_emails array * - Replace email server, username and password * - place an entry in crontab to run it once every hour */

/////////////////////////////////////////////////////////////////// //CHANGE ONLY THESE ENTRIES ///////////////////////////////////////////////////////////////////

$workingdirectory = "/home/****/www/tmp/all/hacked"; ///< The dir where it'll create files

$home = '/home/*****/www'; ///<The folder to prefix to the names of relative path files in $files

$all_emails = array( "g*****m@gmail.com", "d****@gmail.com" ); //List of all email where you want notifications to be sent

$code = "XYLL394"; ///< Use this code in your gmail/email filter for this change notification file as it's body will contain it $from = "contactus@dow*******dia.com"; ///<Sender email id $host = "mail.dow******dia.com"; ///<Email server name $username = "contac******sindia.com"; ///<Login name $password = "*******"; ///<password /*YOUR CHANGES STOP HERE*/ /////////////////////////////////////////////////////////////////// $SRFILE = 'htaccess-hacked.sr'; ///<Name of the serialized file which will hold past sizes and other info of all files in $files array $changesFile = "changes.txt"; ///< All changes will be logged in this /////////////////////////////////////////////////////////////////// require_once "Mail.php"; require_once('Mail/mime.php');

error_reporting(E_ALL | E_NOTICE | E_STRICT);

if(!chdir($workingdirectory)) { print "chdir to $workingdirectory failed"; }

date_default_timezone_set('Asia/Kolkata');

$files = array( 'C:\xampp\tmp/.htaccess', 'forum.********.org/.htaccess', '.htaccess', 'tmp/all/hacked/.htaccess', ); ///< List of relative paths of all files which need to be monitored.

//get the last serialized file

if (file_exists($SRFILE)) { $lastinfo = unserialize(file_get_contents($SRFILE)); assert(copy($SRFILE, "$SRFILE-old")); } else { $lastinfo = null; }

$outarr = array();

$text = ''; ///<It contains files whose sizes have changed $othertext = ''; ///< It contains files who don't exist any more

//read the current size $index = 0; ///<This counts changed files info in $text $index2 = 0; ///<This counts unexistings files info in $othertext

foreach ($files as $file) { $fullpath = "$home/$file";

chmod($fullpath, 0555);

if (file_exists($fullpath)) { $outarray[$file] = filesize($fullpath);

//check if same as last one if (!is_null($lastinfo) and (!array_key_exists($file, $lastinfo) or $lastinfo[$file] != $outarray[$file])) { ++$index; $text = "$index) $file\n$text"; } } else //does not exist; put this information in file only; send no urgent emails { ++$index2; $msg = "$file not found"; $othertext = "$index2)$msg\n$othertext"; } }

//now write the array assert(file_put_contents($SRFILE, serialize($outarray)));

//send the email if any changes if (strlen(trim($text)) or strlen(trim($othertext))) { ///< send notification only when file size changes and not for missing files //write in the tmpfile

$fp = fopen("$changesFile", "a"); assert($fp); fprintf($fp, "------------------------------------------------------\n"); fprintf($fp, "\nToday's date :%s\n", date('r')); if(strlen(trim($othertext))) { fprintf($fp, "\n\tUN-EXISTING FILES FOLLOW:\n%s\n", $othertext); } if(strlen(trim($text))) { fprintf($fp, "\n\tLIST OF CHANGED FILES FOLLOW:\n%s\n", $text); fclose($fp); send_email($changesFile, "URGENT NOTIFICATION(Websites Hacked!): .htaccess changed"); //send urgent notification } } else { print "no changed .htaccess files found\n";

//if the file exists then send it once in a day at night //$hh = date('H'); //get the hour $filename = date('d'); //just to remind that we've sent the file if ( !file_exists($filename)) { assert(file_put_contents($filename, "empty")); $chfile = null;

if(file_exists($changesFile)) { $chfile = $changesFile; } send_email($chfile, "DAILY Notification on: .htaccess change");

//remove yesterday's file $yestday = date('d', strtotime('-1 day'));

assert($filename !== $yestday);

unlink($yestday); } }

function send_email($file, $sub) { global $all_emails, $host, $username, $password,$code,$from;

// if (!file_exists($file)) { // print "Sending no emails as no input file: $file found\n"; // return; // }

$dateinfo = getdate();

$to = $all_emails[0]; for($j=1;$j< count($all_emails);++$j) //append all the emails { $to = "$to , $all_emails[$j]"; }

$subject = $sub; $body = "Change notifications for file; code:$code"; $html = null;

$headers = array('From' => $from, 'To' => $to, 'Subject' => $subject); error_reporting(E_ALL);

$crlf = "\n";

$mime = new Mail_mime($crlf); $mime->setTXTBody($text); $mime->setHTMLBody($body); if($file) { $mime->addAttachment($file, 'application/octet-stream'); } //do not ever try to call these lines in reverse order $body = $mime->get(); $headers = $mime->headers($headers);

$smtp = Mail::factory('smtp', array('host' => $host, 'auth' => true, 'username' => $username, 'password' => $password));

$mail = $smtp->send($to, $headers, $body);

if (PEAR::isError($mail)) { echo("

" . $mail->getMessage() . "

"); } else { echo("Message Sent successfully Thank you. Please Visit Again! "); } }

No comments:

Post a Comment