[thelist] formmail "bad referrer" error, with no apparent cause?

Keith cache at dowebs.com
Sat Dec 8 01:23:27 CST 2001


> Can anyone give me a clue as to what might be causing one user to get
> a bad referrer error on a form?  The cgi script is a slight
> modification of Matt's FormMail.  It hasn't been changed for 6 months,
> it had been working normally, and works when I test it now.  The
> referrer that the script error handler reported as being in error is
> one of the referrers in the referrer array.  

Hi Heather,

It could be a number of things. First thing to do, find out what 
referrer formmail is receiving. Place the following on line 34 (just 
above the @referrer = line) and have your user try it (you might want 
to create a copy with a different name while testing because this 
will kill the script)

print "Content-type: text/html\n\n";
print "referrer is $ENV{'HTTP_REFERER'}";
exit;

That way the script will fail and report back the referrer that it 
received. Once you've done that the problem should be obvious, or 
at least you'll have a starting point. I'd look for a Perl metacharacter 
in the referrer, or no referrer at all (depending on your "slight
 modification").

It's a weird coincidence that you posted a message about formmail. 
Just the other day I was reviewing our server error logs and saw 
that 14 times in the last month different domains on our servers 
were getting "file not found: cgi-bin/formmail.pl" errors. We've never 
allowed a cgi-bin on our servers or allowed formmail. Those errors 
were coming from a robot scanning our cornor of the web, looking 
for a spam relay. Matt Wright's FormMail.pl is the most widely used 
spam relay on the web. And since you are relying on the referrer 
array, your installation IS a spam relay.

A lazy spammer can  trick FormMail into not even using the 
@referrer array and substitute his victim's email address for the 
recipient. But enterprising spammers (ones who come looking for 
you with robots) will send a fake referrer, making FormMail think the 
form is coming from a referrer in your @referrer array, again 
substituting his victim's email address for the recipient. These tricks 
are well documented, easily available, and widely used by 
professional spammers to turn your FormMail into a spam relay 
server. 

In addition to being a spam relay FormMail is a portal for a "denial 
of service attack". Since it's easy to automate using FormMail to 
hijack your server's email program, it's easy to throw a million 
emails through it, bogging your server down or crashing it.

You may think that FormMail's vulnerability is not your problem. In a 
sense you're right, it's Matt's problem, one he's failed to own up to. 
But, have someone stuff a million spam emails through your relay 
and get 10K angry emails back because your server admin contact 
is in the expanded email headers and you'll realize it is your 
problem too.

The good news is: FormMail is easy to fix. 

Remove lines 74, 75 & 76
############
    else {
        $check_referer = 1;
    }
###########
Those lines allow a submission with no referrer (Matt wasn't 
thinking!) and allows a spammer to send 
http://example.com/formmail.pl?message=GOTCHA&recipient=you
@your.com
from a location field (which does not produce a referrer).

That takes care of the lazy spammer. A professional spammer who 
fakes the referrer with an LWP agent is a little harder. FormMail is 
designed to be used by multiple domains sending emails to known 
recipients. If you are letting visitors enter a recipient of their choice 
you have a spam relay by design. But, if your recipient is in a 
hidden field (as it should be) then the script needs to check the 
submitted recipient against an array of approved recipients. To do 
this you need to get a list of approved recipient emails from all of 
the people authorized to have a form pointing to your FormMail 
script. You then add them to an array on the line below $mailprog = 
'/usr/lib/sendmail'; like so

@recipients = qw(me at my.com you at your.com);

(note the space between each email address)

Then on the line below &parse_form; place this line

unless("@recipients" =~ 
/$Config{'recipient'}/){&error('no_recipient')}

That will cause the script to exit reporting that no recipient was 
submitted (technically not true). You can be nice to the bandit by 
changing line 576 from "No Recipient was specified" to "An 
Unauthorized Recipient was specified" but that's up to your sense 
of 'fair play'. 

Please, Heather, make the above changes. This is a hot topic on 
many server mail lists. Subscribe to cobalt-users at list.cobalt.com 
or cobalt-security at list.cobalt.com and bring up FormMail.pl and 
watch the days of bitter ranting. BTW, the above fixes were tested 
by numerous long-time subscribers to those 2 lists and passes the 
minimum recommendations for hardening the script.

Feel free to contact me offlist if you have questions, need help or 
want a fully hardened version of Matt's script.

Sincerly

keith




More information about the thelist mailing list