Why was my PHP script "disabled for security reasons"?

This page is showing a generic answer.
To see a more detailed answer customized for you, type your domain name here:

If you were directed to this page by a message from Tiger Technologies, we have disabled one of your PHP scripts. Our security systems have detected that a spammer has taken advantage of a bug in your script to send one or more messages (probably "spam") to an unauthorized destination.

The rest of this page contains a technical explanation that a programmer can use to solve the problem. If you don't understand this page, please contact the person or organization that provided you with the script — they will know what it means.

When the problem has been fixed as described below, please contact us so we can review your script and make sure that spammers cannot use it to send spam. We will re-enable your script for you; do not re-enable your script without contacting us.

What's wrong with my script?

Your script is written in a way that allows a spammer to use an email header injection attack. It allows a visitor to provide text that is passed directly to the PHP mail() function as one of the headers.

If your script accepts data from a visitor to your website, then uses that data as the "to", "subject" or "additional_headers" parameters of PHP's mail() function without checking to see if the data contains carriage returns or line feeds, a spammer can use your script to send spam.

Can you show me an example?

Here's a simple example of a PHP "feedback form" script that has this problem:

<?php

$to = 'feedback@<your domain name>';
$subject = $_POST['subject'];
$from_address = $_POST['from_address'];
$message= $_POST['message'];

mail ($to, $subject, $message, "From: $from_address");

?>

That looks pretty reasonable, but consider what happens if the spammer submits these multiple lines (including carriage returns and line feeds) as the "from_address":

abc@example.com
Subject: Buy V1agra
BCC: victim1@example.com, victim2@example.net

Buy Viagra from our website, etc.

If the spammer does that, then your script will send the following email message:

To: feedback@<your domain name>
Subject: Feedback Form
From: abc@example.com
Subject: Buy V1agra
BCC: victim1@example.com, victim2@example.net

Buy Viagra from our website, etc.

The message will be sent to all the BCC recipients with the "Buy V1agra" subject line (if a message has two subject lines, the second one is actually used). In other words, your script has been used to send spam — and since our servers have very high-speed connections, a spammer could use this trick to send tens of thousands of messages within a few minutes.

But isn't this is unlikely? How would a spammer find my script?

Unfortunately, it's not unlikely at all. In fact, if Tiger Technologies has disabled one of your scripts and sent you a link to this page, it's probably because a spammer has already used this method to make your script send a message to an unauthorized destination.

Spammers use automated testing tools to send many different combinations of unusual input text to any script that they can find via a search engine. It's not uncommon to see a spammer try hundreds of possible combinations of unusual input text to find a way to exploit this kind of weakness.

Also keep in mind that even though most Web browsers don't allow your visitors to send carriage returns as part of single-line text boxes, spammers use special software that allows this. You probably won't be able to use a normal Web browser to duplicate what they're doing with carriage returns or line feeds, but that doesn't mean your script is safe.

So what can I do?

To fix this problem, you need to check that the input text does not contain any "carriage return" or "line feed" characters before you use it in the "to", "subject" or "additional_headers" of the mail() function.

Here is code that fixes the example script we mentioned above, for example. It adds a new function named CheckForProhibitedCharacters and uses that function to make sure that no "header" data provided by the website visitor contains extra lines:

<?php

$to = 'feedback@<your domain name>';
$subject = $_POST['subject'];
$from_address = $_POST['from_address'];
$message= $_POST['message'];

# Verify that visitor-supplied data used as mail headers does not contain
# carriage returns or line feeds. There is no reason for headers like
# "To", "From", Subject", etc., to ever contain carriage returns or
# line feeds; it almost always indicates some kind of spam attack.

CheckForProhibitedCharacters ($subject);
CheckForProhibitedCharacters ($from_address);

# In this example, we don't need to check $to, because no part of
# it was supplied by the website visitor. And we don't need to check
# $message because it is not being passed to mail() as a header, and
# it may actually contain legitimate carriage returns or line feeds.

mail ($to, $subject, $message, "From: $from_address");

function CheckForProhibitedCharacters ($field_input)
{
    # die() if the field contains a carriage return or line feed
    if (preg_match ("/[\r\n]/", $field_input))
    {
        die ("Input field contains a prohibited character");
    }
}

?>

In other words, you simply use the new function to check any variable that is both supplied by the website visitor and passed as a mail() header.