README.security
===============


Author: Ronald F. Guilmette <rfg@monkeys.com>
---------------------------------------------

Last edit: Tue Jan 29 16:19:55 PST 2002
---------------------------------------


The 1.9s version of Matt Wright's FormMail script was developed for
the benefit of sites that already make use of various earlier and
unsecure versions of FormMail, including the 1.9 version, which may
still allow remote exploitation by spammers.  Such sites may elect
to use this version of the FormMail script AT THEIR OWN RISK, however
if at all possible, I advise against doing so.  I _believe_ that I
have corrected all of the security problems that allow this script
to be hijacked by remote spammers, but generally speaking, FormMail
has a bad history os serious security problems and YOU WOULD ALMOST
CERTAINLY BE BETTER OFF DEVELOPING YOUR OWN MAIL SCRIPT FROM SCRATCH.

Still, I understand that for many sites lacking in programming talent,
replacing an already-installed FormMail script with a more secure
version of the same thing may be the only viable choice.

Several changes were made to the FormMail script in version 1.9s in
an attempt to clean up and remove all of the insecurities in the
script that are known to the author at the time of this writing.

Specifically, all of the former code that attempted to validate
incoming HTTP requests based on the value of the HTTP_REFERER en-
vironment variable (whose value is derived from the client-supplied
HTTP Referer: header) has been removed.  This code, in addition to
being deeply flawed with respect to security, was utterly pointless
anyway because the HTTP client can easily set the value given in
the HTTP Referer: header to anything he wants.  Thus, even if the
code in the prior (1.9) version of the script which allowed a null
HTTP_REFERER value to `pass' the check were removed, it would still
have been the case that an attacker could get past the HTTP_REFERER
test simply by supplying a value in the HTTP Referer: header that
made the script happy.  Such values would have been easy to find
(or guess) in any case.  So the useless check on HTTP_REFERER was
simply removed from the script.  The script now relies entirely on
new (and more secure) code that checks that the `recipient' address(es)
is/are in fact allowed recipient addresses for the locally-installed
instance/version of this script.

Formerly, the FormMail script checked an array called `@recipients'
to see if a given recipient address was allowed by the person who
installed FormMail.  But the code that did that checking contained
many obvious security loopholes.  So that code has all been entirely
rewritten and replaced in this version (1.9s) of FormMail.   Now, in
version 1.9s, we check each recipient address against the values given
in two arrays that are supposed to be defined by the installer at
install-time.  These are the `@recipient_addresses' array and the
`@recipient_domains' array.  Their meaning and usage should be obvious.
See the regular README file for more information about setting up
these arrays are install-time.  It is believed that the new recipient
address checking code is secure, and that it will properly disallow
all attempts to trick FormMail into sending e-mail to any e-mail
address other than one which the installer of the script intended to
be a FormMail e-mail recipient.

(Note that as part of the rewrite of the recipient address checking
code new checks were also included to insure that no client-supplied
recipient e-mail will be allowed to contain either a percent-sign (%)
character or an exclamation-point (!) character.  Such characters, if
allowed, would leave open a loophole via which a spammer might be able
to trick the local FormMail/mailserver combination into sending e-mail
messages to other domains, even if that would otherwise seem to be pro-
hibited by the definitions of the two @recipient_* arrays.)

In addition to the removal of the HTTP_REFERER code and the rewrite of
the recipient address checking code, some other security related changes
have also been implemented in this version of the script:

1)  The `email' and `realname' CGI parameters now have carriage returns
and linefeeds properly stripped out before these values are printed to
the local mail server.  (The lack of such stripping was formerly a big
security loophole.)

2)  The envelope sender address is now forced to the installer-supplied
$mail_admin value (via the Sendmail -f option).  This should help to
insure that any undeliverable bounce messages that might be generated
if and when the script attempts to send to some bogus address are re-
turned to some known/fixed mailbox that an attacker cannot override.
(Note however that it is still the installer's responsibility to set
this to some e-mail address corresponding to some local mailbox that
_IS_ in fact frequently and routinely monitored by some live human.)

3)  All indications of the specific version number of the script have been
entirely removed from all script-generated HTML messages.  (There's no sense
in giving attackers extra and potentially useful information.)

4)  In preparation for the possibility that spammers may still be able to
find some clever way of hijacking even this (secured?) version of FormMail,
several new X- e-mail headers are now generated by the script and appended
to the other e-mail header lines (To:, From:, Subject:) that are generated
by the script:

    o	A new "X-Generated-By: Matt Wright's FormMail.pl v1.9s" header
	will be attached to each generated e-mail message, thus indicating
	exactly what piece of software generated the e-mail message.

    o	A new "X-Script-URL: <<url>>" header will be attached to each
	generated message, where the <<url>> part will be set to the
	full URL by which the script was invoked.  This will make the
	job of tracking down the broken FormMail scripts a lot easier
	if this script should ever be compromised by spammers in the
	future.

    o	A new "X-Originating-IP: [<<dotted quad>>]" header will be attached
	to each generated message, where the <<dotted quad>> part will be
	the dotted-quad representation of the IP address of the specific
	HTTP client that caused the script to be invoked.  This additional
	information may be of some help in tracking down perpetrators, if
	and when this version of FormMail is ever cleverly hijacked in the
	future.  (We _believe_ that we have made such hijacking impossible,
	but one can never prove the absence of yet more problems/bugs, so
	better safe than sorry.)

	(Note that the information contained in this new header may perhaps
	only be marginally useful... even if this version of FormMail is in
	fact later found to still be vulnerable to hijacking by outside
	spammers... because the IP address given in this header may perhaps
	only indicate the IP address of whatever anonymizing proxy the
	spammer used/abused as he was tricking FormMail into sending out
	his spam.)

    o	If any one of the comma-separated substrings of the `recipient' CGI
	parameter is found to NOT match anything in @recipient_addresses or
	in @recipient_domains, then a security notice is mailed to the local
	$mail_admin.  This should help a lot to catch spammers who may be
	trying to perform experiments on a given locally-installed copy of
	FormMail in preparation for an attempted spam run.

5)  In addition to all of the other changes noted above (all of which are
focused on preventing abuse of FormMail by outside spammers) the 1.9s-p2
version of FormMail also fixes all FormMail security holes relating to
possible cross-site scripting attacks.  (``Cross-side scripting is a
generic name for an entire class of possible security exploits which (a)
can potentially be used to either (a) execute various `server-side include'
directives on the system hosting the CGI script or which (b) can potentially
be used to ``trick'' end-user browsers into executing client-side scripts
or client-side commands with more or different privledges than they would
normailly be given when they come from an untrusted site.)

Problems with possible cross-site scripting holes have all been closed now
by insuring that each name and/or value in each CGI name=value parameter
pair will have any embedded < or > characters they contain converted to
their HTML equivalents, i.e, &lt; and &gt;.  Also, all documents returned
by FormMail now have their character set forced to "iso-8859-1".

One other small cosmetic change has also been implemented in this version
of FormMail, namely the addition of a -bm (be a mailer) option flag to the
invocation of the local mail server.  When the local mail server is in fact
Sendmail, this flag isn't needed, because it is assumed by default.  However
I previously experienced some trouble with another ``mailer'' type CGI script
when I tried to hook it up to Postfix (the mostly-compatible Sendmail re-
placement) unless I included a -bm option in the invocation line.  So just
to make extra sure things will work right, I added the -bm option to the
line that invokes the local mail server.  It never hurts to have it there,
and in some cases, it may perhaps help.
