HaLe Blog twitter
HaLe Blog Rss

Apache2 : webserver sending spam – how to find out what is sending it.

Posted by lhe | Posted in Apache2, General, Linux (Ubuntu) | Posted on 23-04-2010

9

Recently we started getting spam complaints for mails that were sent from our server, obviously not deliberately.

Now since we have a whole bunch of sites running on our server, finding out which one was hacked, promised to be a tedious job.
Until… we found this post : How To Log Emails Sent With PHP’s mail() Function To Detect Form Spam

This script will write out all sites using the PHP sendmail function into a log file, making it very easy to find out where the spam is coming from.
It saved us from a very very long night!
We have put the whole content of the wonderful article by till on our blog and made some minor modifications to the explanation.

Hope it helps!

1 Installing the wrapper script

Create a new file that will contain the script:

touch /usr/local/bin/phpsendmail

Use nano, vi or your favorite text editor to edit the file you just created and enter this script:

#!/usr/bin/php
<!--?php 
 
/**
  This script is a sendmail wrapper for php to log calls of the php mail() function.
  Author: Till Brehm, www.ispconfig.org
  (Hopefully) secured by David Goodwin <david @ _palepurple_.co.uk-->
*/
 
$sendmail_bin = '/usr/sbin/sendmail';
$logfile = '/var/log/mail_wrapper.log';
 
//* Get the email content
$logline = '';
$pointer = fopen('php://stdin', 'r');
 
while ($line = fgets($pointer)) {
        if(preg_match('/^to:/i', $line) || preg_match('/^from:/i', $line)) {
                $logline .= trim($line).' ';
        }
        $mail .= $line;
}
 
//* compose the sendmail command
$command = 'echo ' . escapeshellarg($mail) . ' | '.$sendmail_bin.' -t -i';
for ($i = 1; $i &lt; $_SERVER['argc']; $i++) {
        $command .= escapeshellarg($_SERVER['argv'][$i]).' ';
}
 
//* Write the log
file_put_contents($logfile, date('Y-m-d H:i:s') . ' ' . $_ENV['PWD'] . ' ' . $logline, FILE_APPEND);
//* Execute the command
return shell_exec($command);
?&gt;

If you use a different Linux distribution than Debian, the sendmail binary might be in a different location than /usr/sbin/sendmail and you have to change the sendmail path in the line $sendmail_bin = ‘/usr/sbin/sendmail’; of the script.

Now make the script executable…

chmod +x /usr/local/bin/phpsendmail

… and create the logfile and make it writable:

touch /var/log/mail_wrapper.log
chmod ugo+w /var/log/mail_wrapper.log

2 Modifying the php.ini

Now we reconfigure PHP so that it uses our wrapper script to send the emails.

Open the php.ini file…

vi /etc/php5/apache2/php.ini

… and uncomment the sendmail_path line and put the path to the script we created

; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
sendmail_path = /usr/local/bin/phpsendmail

If you use php as cgi, with suphp or as fcgi, then change the same lines in the file /etc/php5/cgi/php.ini, too.

Restart the Apache webserver to apply the changes.

/etc/init.d/apache2 restart

3 Test the setup

To test this setup, create a new php file with the name mailtest.php in one of your websites with the content:

 

Then open the file in a webbrowser to execute it. The test message should be logged now into the logfile. Check this with the command:

cat /var/log/mail_wrapper.log

Off course, don’t forget this wonderful command:

tail -f /var/log/mail_wrapper.log

Comments (9)

$logfile = ‘/tmp/mail_php.log’;

Should be change in:

$logfile = ‘/var/log/mail_wrapper.log’;

@ReMARKable
Hey Mark!

you are absolutely right. I have updated my post. Thank you for the feedback !

Man, I’ve been looking for such a solution for a long time. Thank you a million times!!!! :)

Hi Cos

you are very welcome! :)

cheers
Leiv

That is a VERY handy tool! Thanks a bunch for sharing! Works like a charm.

Your welcome!

Really helpful, great work. Thank you!

Tried this and when I changed the php.ini file send mail stopped working. The binary is in the same place and I checked the file permissions. Using FreeBSD.

@Matt
I tried this script on a older cent0s box and it failed. I checked my message log and found that php 4 did not have a file_put_contents() function. I found one on the php.net site in the comments for file_put_contents(). Add this to the phpsendmail file under the comment at the top of the script and it should fix your problem.

function file_put_contents($filename, $data) {
$f = @fopen($filename, ‘w’);
if (!$f) {
return false;
} else {
$bytes = fwrite($f, $data);
fclose($f);
return $bytes;
}
}

Write a comment