Is Your PHP Web-form Hacker Proof?

Several months ago, my friend informed me that he was seeing a large volume of email spam coming from one of my legacy sites. After investigating, we found that my “contact” page was the source. A hacker was spamming people through the contact form on my website! The page in question was a simple PHP script where people could provide an email address and a short message that would be emailed to me. So here’s the question of the day: How did they make it email other people with their own custom email messages?

Most people may not be aware of this, but the culprit is the PHP mail() function. The relevant portion of the definition is as follows:

bool mail ( string $to, string $subject, string $message [, string $additional_headers] )

So most people would probably do something like this:

mail($to, $subject, $message);

But by default, this will create an email address with some ugly “from” address like, root@localhost. What if you want to have a “from” email address, such as the person who filled out the form?

mail($myEmailAddress, $subject, $message, “From: $fromAddress”);

But don’t you need to escape it? Well, a lot of beginners (like I did when I started out), don’t realize that “addslashes” does nothing. A hacker could provide additional headers in your script by typing in the following in your web-form:

me@fakeemail.com \r\n

Followed directly by another header:

Bcc : otherpeople@hotmail.com [ignore spaces]

The above code would send an email to otherpeople@hotmail.com through the BCC field. That alone doesn’t sound too threatening. However, it is actually possible to inject in a message body, attachments, other recipients, a new subject, etc. at this point. A hacker can completely re-format your original email. In essence, they can post data to your form to make it do something completely different than what you had intended.

And judging from the fact that I wasn’t getting emails, I would assume that they can suppress the original “to” email address as well, making the breach completely unnoticeable.

To fix this, make sure you filter arguments that get passed in as headers by removing the \r and \n characters.

$fromAddress = str_replace(array(“\r”, “\n”), ”, $formAddress);

As always, remember my code examples tend to use curly quotes that PHP won’t recognize.

So, is your form hacker-proof?

Further reading on this topic can be found here.

Note: I had a horrible time trying to make this post. Apparently, WordPress doesn’t like the word “Bcc[colon]” appearing anywhere in the post! How lame!?

  • Rash

    yes it is.

  • http://www.oldnavy.com thompson

    please i wanna learn how to hack credit cards i am thompson from usa new york 27 can u teach me or even send me some credi cards

  • http://postworthy.com/WorthyGroups/Information_Security/50.aspx Information Security

    Great article, it is good to see people learn from their mistakes and try an help others avoid problems. Keep up the good work.

  • http://www.michikono.com Michi

    I am fairly certain my solution is correct. I am not looking for the text string “backslash n” and “backslash r”, rather, I am looking for the converted equivalents. So if someone passed in those hex values, they would get converted into carriage returns and new lines before I look at them. In fact, never should I see the string text “0x0A” since at that point, it’s already converted into the \r or \n.

  • Mihai Roman

    Hello,

    I think this is not enough:
    “$fromAddress = str_replace(array(“\r”, “\n”), “”, $formAddress);”

    Instead of “\n” or “\n” someone might try to use the hexadecimal equivalent for those characters.
    “\n” = 0x0A
    “\r” = 0x0D
    Still this isn’t enough, but for further reading I would also recommend the link you already provided.

  • Pingback: ./blog » PHP mail() function security

  • http://htmlpurifier.org/ Ambush Commander

    The usual solution to mail() woes is to use a mailing library such as PHPMailer or, my personal favorite, SwiftMailer.