Find the php script thats sending mails

9,792

Solution 1

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.

Solution 2

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/

Solution 3

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.

Share:
9,792

Related videos on Youtube

adam
Author by

adam

Updated on September 17, 2022

Comments

  • adam
    adam over 1 year

    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
    adam about 14 years
    thks for the replay, the problem is that is a shared hosting and for each domain the is a dedicated access log.
  • Pekka
    Pekka about 14 years
    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.
  • WheresAlice
    WheresAlice about 14 years
    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.
  • adam
    adam about 14 years
    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
    adam about 14 years
    php 4.x here ( got some old apps that not viable porting to php 5.x )
  • adam
    adam about 14 years
    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
  • WheresAlice
    WheresAlice about 14 years
    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.
  • labradort
    labradort about 14 years
    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
  • Richard Salts
    Richard Salts about 14 years
    Yes, unfortunately you're going to have to grep through all of them.
  • labradort
    labradort almost 10 years
    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.
  • Tom McQuarrie
    Tom McQuarrie over 9 years
    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.
  • Eric Kigathi
    Eric Kigathi almost 9 years
    In a shared hosting environment this might not pin-point the exact script or might result in multiple false positives
  • labradort
    labradort over 3 years
    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.