9

Is there any way for me to find the php script that is sending emails.

I have apache+php ( no mod_suphp neither suexec ) in a "standard" install, and i want to find out witch php script is sending emails, when i check the logs i just see the uid of the user that's sending the emails ( in my case apache ) but i want to find out the script that's originated the email.

Is it possible or i must install suexec or mod_suphp to keep trac of that ?

Thks for the help.

adam
  • 353
  • 2
  • 5

6 Answers6

9

php 5.3 was slotted to get better mail tracing, but I'm not sure if that happened. (edit: yes php 5.3 has logging built in now - php.ini has the config variable mail.log which will log use of mail from php code.)

We solved the problem by making sendmail a wrapper shell script.

In php.ini set a new mailer. E.g.:

sendmail_path = /usr/local/bin/sendmail-php -t -i

The sendmail-php script simply uses logger to get info, and then calls the system's sendmail:

#!/bin/bash

logger -p mail.info -t sendmail-php "site=${HTTP_HOST}, client=${REMOTE_ADDR}, script=${SCRIPT_NAME}, filename=${SCRIPT_FILENAME}, docroot=${DOCUMENT_ROOT}, pwd=${PWD}, uid=${UID}, user=$(whoami)"

/usr/sbin/sendmail -t -i $*

This will log to whatever your mail.info is set to in the syslog.conf file.

Another suggestion is to install suhosin php extension to tighten up loopholes in PHP, unless you are running Debian or Ubuntu where this is already the default.

Wil Cooley
  • 361
  • 3
  • 10
labradort
  • 1,169
  • 1
  • 8
  • 20
  • php 4.x here ( got some old apps that not viable porting to php 5.x ) – adam Apr 07 '10 at 13:49
  • No problem, this wrapper will do the trick. It is external to php. I mentioned php 5.3 merely as this lack of a logging feature was slated to be fixed by then. The wrapper works very well and we were able to pinpoint a flawed script by a user which was permitting spam. – labradort Apr 07 '10 at 13:53
  • thks, i guess i'm going to take your approach. thank you – adam Apr 07 '10 at 13:55
  • 1
    Hi, dont now why but the "script=${SCRIPT_NAME}, filename=${SCRIPT_FILENAME}" is not returning anything see: 7 20:24:08 gateway logger: sendmail-php: client=,filename=, pwd=/var/www/html/mail, uid=48, user=apache – adam Apr 07 '10 at 18:34
  • Are you sure it was set up correctly? If it was unknown as a predefined variable in your PHP environment, you should be seeing also: "script=," in the logged output. Check what you set up again very carefully. You could try: $_SERVER['SCRIPT_FILENAME'] You might be able to look up more variables for logging from the PHP documentation on Predefined variables: http://www.php.net/manual/en/reserved.variables.server.php – labradort Apr 07 '10 at 19:19
  • This accepted answer is now very old (for php 5.3) and please do not use on modern versions of PHP. mail.log in php.ini is likely all you need. – labradort Jan 26 '21 at 14:29
4

The solution to this actually requires a few steps. labradort's solution above doesn't actually work since the logger script is a bash script, not php, and the bash script has no access to php's variables, so the logs come out blank. Basically whatever you want to log needs to be saved to environment variables in php prior to sending the email so the logger has access to the data. Since you're trying to detect other user's scripts, not necessarily your own, you have no control over the php code, so you need to use PHP's auto_prepend_file feature to ensure that all executed php runs your initialisation code before everything else. I prepended the following code via php.ini to ensure I have the data I need in the logger:

<?php
/**
 * This passes all SERVER variables to environment variables, 
 * so they can be used by called bash scripts later
 */
foreach ( $_SERVER as $k=>$v ) putenv("$k=$v");
?>

I put together a full tutorial on how to get this working here: http://mcquarrie.com.au/wordpress/2012/10/tracking-down-malicious-php-spam-scripts/

  • The wrapper script did work on Redhat and Debian Linux's implementation of php defaults back when it was php 5.2 and earlier. I'm simply using mail.log = /var/log/apache-mail.log these days and it does what I need. – labradort Jun 18 '14 at 13:05
  • 1
    This is precisely how the shellshock bug is exploited. I seriously don't recommend doing things this way. – Ben Hitchcock Oct 09 '14 at 00:57
  • You have a point. You could certainly run the variables through a sanitise function to strip out anything harmful, like "() { :;};". Actually probably a good idea to prefix the variable names as well, with something like "PHP_", just in case there's an environment variable name clash. – Tom McQuarrie Oct 09 '14 at 03:44
2

There is a patch for PHP that will show which script is generating the emails by adding a header to the email being sent. I haven't tested it since I'm not keen on patching core PHP, but I've heard good things.

WheresAlice
  • 5,530
  • 2
  • 24
  • 20
  • 1
    This sounds like an excellent way to go. +1. However, if you're managing a shared host with multiple clients, you may want to inform those clients about the header, or redirect the output into a log file instead. – Pekka Apr 07 '10 at 12:11
  • Yes maybe it's the way to go but at a certain point it my be a security issue, all the people is going to now what script is sending email, poorly made script's is just inviting to get hacked. Redirect to a log maybe it's better – adam Apr 07 '10 at 13:45
  • Poorly made scripts shouldn't be on the server in the first place, people will find them if they are there (particularly if they are part of a popular cms system). But I get your point that there is maybe a case against this solution. – WheresAlice Apr 07 '10 at 18:55
0

You're going to have to grep the access logs for something that fits the timeframe of when the messages were added to the spool.

Richard Salts
  • 755
  • 3
  • 17
0

May be just search through source files for "mail(" substring?

  • That is sometimes worth looking at, and in particular looking at the source code surrounding it for any vulnerabilities for spammers to use. But with lots of complicated php scripts owned by many people on a shared host, it's not the solution for this problem. – WheresAlice Apr 07 '10 at 12:49
  • In a shared hosting environment this might not pin-point the exact script or might result in multiple false positives – Eric Kigathi May 25 '15 at 20:08
0

Simply enable these on your php.ini

mail.add_x_header = On
mail.log = /var/log/phpmail.log

then create that file and give the write permission. Take an eye on it after that.

Kevin Nguyen
  • 189
  • 1
  • 2
  • 8