PHP: Preventing X-PHP-Script Exposure of Variables
Not so long ago a patch was added to the PHP source code that, when mail is sent using the mail() function, has the effect of exposing both the script address on the server and the IP address of the remote user (the person submitting a contact form that sends email for example).
The logic behind this is clear. So many open source PHP applications have security holes allowing emails to be sent that it became necessary to find a way to identify the source. Before this patch it was not possible for the average user to do so, and certainly not for the recipient of spam sent using those techniques.
The problem is that, without much fanfare, many sites that are otherwise secure are having information about their technology and directory structure (the path to scripts in protected areas) and private IP addresses (the home of office IP address of the user) exposed every time a script is used that sends emails from the server.
A Simple Solution
Suggested solutions for those who don't want the X-PHP-Script mail headers to appear range from self-editing the patch to change the behaviour, to avoiding use of the PHP mail() function altogether. Not entirely useful.
Examining the patch contents shows a simpler solution. It seems it's relying on PHP $_SERVER variables to add a mail header in the following format to outgoing emails:
X-PHP-Script: <server_name><php_self> for [<forwarded_for>,]<remote-addr>
So what could be simpler than overwriting those variables before the mail() function is called, and then restoring them afterwards. If you already use a wrapper for sending mail then this is a once-off change. Otherwise, if you call the mail() function directory from your scripts, you'll have to modify each instance.
For our purposes it was sufficient to display just the homepage address (/) in place of the full path to the script (PHP_SELF) and to replace the users IP address (REMOTE_ADDR) with our own (SERVER_ADDR):
<?PHP // prevent user/script details being exposed in X-PHP-Script header $oldphpself = $_SERVER['PHP_SELF']; $oldremoteaddr = $_SERVER['REMOTE_ADDR']; $_SERVER['PHP_SELF'] = "/"; $_SERVER['REMOTE_ADDR'] = $_SERVER['SERVER_ADDR']; // send the email mail($to, $subject, $message[, $additional_headers[, $additional_parameters]]) // restore obfuscated server variables $_SERVER['PHP_SELF'] = $oldphpself; $_SERVER['REMOTE_ADDR'] = $oldremoteaddr; ?>
You can also disable the patch entirely by using unset() on one or more of the relevant $_SERVER variables.
You might also consider writing your own wrapper for the mail function that gives you the option of disabling X-PHP-Script for protected scripts, but allowing the default behaviour for public forms. That is beyond the scope of this article.
Comments and feedback are welcome as always through our Feedback link below.
- PHP mail() header patch
- PHP Bugs: #19538: No way to identify source of email sent by mail()
- Dotdeb » Blog Archive » PHP 5.3.0 RC2 packages for Lenny