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.

6 Answers 6

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.

6
  • php 4.x here ( got some old apps that not viable porting to php 5.x )
    – adam
    Apr 7, 2010 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 7, 2010 at 13:53
  • thks, i guess i'm going to take your approach. thank you
    – adam
    Apr 7, 2010 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 7, 2010 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: php.net/manual/en/reserved.variables.server.php
    – labradort
    Apr 7, 2010 at 19:19
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/

3
  • 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, 2014 at 13:05
  • 1
    This is precisely how the shellshock bug is exploited. I seriously don't recommend doing things this way. Oct 9, 2014 at 0: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. Oct 9, 2014 at 3: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.

3
  • 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 7, 2010 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 7, 2010 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. Apr 7, 2010 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.

2
  • thks for the replay, the problem is that is a shared hosting and for each domain the is a dedicated access log.
    – adam
    Apr 7, 2010 at 12:04
  • Yes, unfortunately you're going to have to grep through all of them. Apr 7, 2010 at 22:31
0

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

2
  • 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. Apr 7, 2010 at 12:49
  • In a shared hosting environment this might not pin-point the exact script or might result in multiple false positives May 25, 2015 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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .