Anders Brownworth

Form Post Hijacking

AKA: Email Form Header Injection

The Problem.

Spammers are constantly being blacklisted and kicked off of networks. Because of this, tricking a non-spamming website into sending spam has become a high priority. One way for spammers to find vulnerable webservers is to test for CGI applications that would allow the spammer to enslave the webserver. Once a vulnerable webserver is found, the spammer can mask the true source of his spam while the enslaved webserver does the bulk of the work.

How do they do that?

A common task websites do is send an email to the owner of the website with whatever data someone has entered into a form. For example, one such script that does this is called formmail.pl or formmail.cgi from Mat's Script Archive. In this script (as well as many others like it) some fields in the form are used directly in the header of an email. (for example, the Reply-To: field in the email is sometimes set to whatever the user of the form entered in the field called "email" so the owner of the website can easily hit "Reply" to that email and send a response.) If these fields are included unmodified, a spammer can simply overwrite the remaning header lines and effectivly submit any email they wish to through the underlying email system, effectivly enslaving the webserver / email system to send spam.

How exactly do they exploit the script?

The destination of an email is set in its headers. Headers, as everything else in an email, are just lines of text. What seperates the headers from the body of an email are just two blank lines. If your formmail script places anything in the header of an email that is unmodified from what the web user entered, they could easily add those two blank lines. This, of course, would just truncate the headers early and make the body of the email contain some of the headers as well. However, if the web user decides to throw in a few more headers before sending the two blank lines, the underlying email system will listen to those as well. So what the spammers are doing is including a "Bcc:" list of spam victims to the email. When the email subsystem gets the email, it blindly follows what is written in the headers and happily sends one copy of the message to each person listed in the "Bcc:" line. Now of course spammers will probably also add their own subject line and some spam content to the email.

In order to find vulnerable webservers to prey on, spammers usually test the form by sending a sample through that is Bcc'd to and email address they have access to. Usually this is some throw-away address such as a hijacked AOL address. Webmasters are usually alerted to this when they see 5 to 10 trial emails in usually less than one second. They Google the address and hopefully find a page like this one which explains what is going on.

So what can be done about it?

The simplest way to mitigate the danger is to disallow any linefeed or carriage return characters in fields used in email headers therefore disabeling an attacker's ability to add those two blank lines and trick your mail system into sending whatever they want. Then the problem becomes one of cleaning up a little annoyance rather than being enslaved to do a spammer's bidding.

Huh? How do I do that?

Well, this is where it becomes a little complicated. The answer to that question depends on what software the form processor on your webserver is using. If you didn't write your own form processor, your first move is probably to go ask the people that helped you set up your website. Most common form mailers have had bug fixes released since this vulnerability first came out. Have your web hosting provider update their form post code.

If you know what you are doing, check all fields in forms that are used in email headers and strip out the carriage return (\r) and line feed (\n) characters. In perl, this is done like this:

$field =~ s/\r/ /g; $field =~ s/\n/ /g;

If you are using PHP, you can do this for each variable used in email headers:

$_POST['email'] = preg_replace("/\r/", "", $_POST['email']); $_POST['email'] = preg_replace("/\n/", "", $_POST['email']);

How do I know if I've been hacked?

As most form to email scripts don't write down what they are doing in a file somewhere, the best way to tell if your setup has been enslaved to send spam is to check your mailserver logs. If you are with a web hosting provider, they can usually check the logs for you.

What should I do if I've been hacked?

You should update your form mailer scripts so continuing attempts are not successful. (do this as described above) The you might want to chase down the throw-away spammer email address used to test for the vulnerability. Most I have seen to date have been addresses at AOL, so you should complain to abuse at aol.com or, as this is a Terms of Service violation, to tosgeneral at aol.com. Many people have already done so with limited effect, so don't expect AOL to come swooping in and fix everything, but its at least covering the bases.

OK, so I'm clean. Now how do I stop the annoying test emails?

Again, go ask your hosting provider. However, if you have to make the edits on your own, find some fingerprint in the email that flags it as obviously bad. Like if the email field contains the characters "Bcc:", chances are you are looking at a probe for vulnerability. Just put an "if" statement around the block of code that sends you an email that tests for that. Don't forget to ignore case so "Bcc:" and "bcc:" are caught. Alternativly you could just look for the two blank lines, however you should be carefull about "\r\n\r\n" and "\n\n" which both will be interpreted as two blank lines. If you are going to do it this way, I suggest you kill all "\r" characters and then search for "\n\n".

What else can be done?

A better (though more complicated) way to get around all of this is to require something that is easy for a human but hard for a computer to do. One such method that is quite popular is to use a Captcha image with some text in it that the user must enter before submitting the form. Personally, I don't like the terrible user experience captcha imposes so I favor an image based recognition requirement to submit the form such as the one at the top-right on this page. As you reload the page, notice the images change. The downside with this method is that it takes some substantial server-side programming, which again is heavily dependant on your particular setup. However if you head over to JustHumans.com, you can find a hosted version of this system. Just sign up for an account and generate some JavaScript code to replace your submit button.

I want a more technical explanation with an example!

Consider a CGI form that accepts a form variable called "reply-to" which gets inserted into the headers of a comments email getting sent to the webmaster. The resulting email that the CGI sends to the local email system would look like this:

From: My Comment Form 
To: me@example.com
Reply-To: webuser@company.com
Subject: New Comment!

I like your website. Thanks for the resource.
The underlying email system gets this email and processes it as you would expect, sending a copy of this message to me@example.com.

Now, a spam sender wants to attack this form so they fill out all the fields just like before but they instead send this to the CGI form variable called "reply-to":

webuser@company.com
Bcc: joe@foo.com, jane@bar.com
Subject: Buy Viagra!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Get your viagra here! http://xxx.viagra.com/xxx
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Looks a little dicey, doesn't it? With an un-checked form processor, the resulting email sent to the email subsystem will look like this:
From: My Comment Form 
To: me@example.com
Reply-To: webuser@company.com
Bcc: joe@foo.com, jane@bar.com
Subject: Buy Viagra!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Get your viagra here! http://xxx.viagra.com/xxx
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Subject: New Comment!

I like your website. Thanks for the resource.
Because the reply-to CGI variable includes new-line characters and a bunch of addresses to spam, the attacker can fool the mailer into thinking the Bcc line and the Subject are legitimate. So joe@foo.com and jane@bar.com get an email with the subject "Buy Viagra!". Sneaky, huh?

Again, to protect against this, all we need to do is to get rid of return (\r) and newline (\n) characters. in all CGI form fields used in email headers. If we did that, the email to the underlying subsystem would instead look like this: (lines wrapped for readability)

From: My Comment Form 
To: me@example.com
Reply-To: webuser@company.comBcc: joe@foo.com, jane@bar.c
omSubject: Buy Viagra!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!Get your viagra here! http://xxx.viagra.com
/xxx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Subj
ect: New Comment!
Subject: New Comment!

I like your website. Thanks for the resource.
and the underlying mail subsystem would send the email as expected. Granted you probably don't want this email and you will likely get many of them, but that's what JustHumans.com is for.

If you have other comments, post them on my blog post covering form spam. Link to this page if you think it has been helpfull so others can find it.