Re: Secure Form Script?
From: Tim Tompkins (timt_at_spiderlinks.org)
Date: Fri, 21 May 2004 13:31:09 -0700 To: Beth Skwarecki <firstname.lastname@example.org>
From the perspective of a web-app developer, I feel much better knowing
that I'm piping to sendmail for two main reasons:
* The mail queue is maintained by an existing, reliable service. If my
webapp were to attempt to directly deliver every message and the
destination mail service were not available, I'd either have to discard
the message or develop my own queue. This issue is especially critical
when sending receipts where we would like to make every possible effort
to ensure that the customer receives a receipt for their purchase. And
I certainly would not want to develop my own queue when I already have
postfix running to handle that.
This is also an issue when it comes to delivering bulk mail, where
postfix is much more sophisticated in its queue management than I'd care
to undertake in a perl script for hundreds of thousands of messages.
Besides, such a service already exists. Why attempt to reinvent it?
* Handing the message off to sendmail/postfix ensures that I'm not
holding up a web server process while my webapp attempts to deliver an
email message. Besides tying up resources unnecessarily, this could
potentially cause the http request to timeout and/or the end user to
think that the web server did not respond to the request, and they may
attempt to re-submit their order. In any case, given that the time to
perform credit card authorization is already a variable in the length of
a request, I'd prefer not to add mail transport to it.
Beth Skwarecki wrote:
> It's silly to be piping things to sendmail this way in perl. There are
> two reasons why:
> 1) To expand a bit on Bryce Porter's comments, it's much safer to use
> system()'s built-in argument handling than to attempt to sanitize
> arguments yourself before putting them all together on a command that
> the shell gets to execute:
> system LIST
> system PROGRAM LIST
> Does exactly the same thing as "exec LIST", except
> that a fork is done first, and the parent process
> waits for the child process to complete. Note
> that argument processing varies depending on the
> number of arguments. If there is more than one
> argument in LIST, or if LIST is an array with more
> than one value, starts the program given by the
> first element of the list with arguments given by
> the rest of the list.
> In other words, the first argument to system() is the command, but
> subsequent arguments are given to the command as its argv, *NOT* just
> stuffed onto the command line. This way, a "; rm -rf /" won't be
> executed as its own command, but just passed as an argument to the
> program (which may then ignore it, give an error, etc, as it pleases)
> 2) HOWEVER, it's silly to be using sendmail at all, in most cases.
> This is what the perl module Mail::Sendmail is for. You give it a hash
> with all the headers you want to send, and it sends directly (it is
> *not* a wrapper around the sendmail binary; it works on all platforms,
> even when sendmail is not installed):
> use Mail::Sendmail;
> my %mail = (
> To => 'email@example.com',
> From => 'firstname.lastname@example.org',
> Subject => 'this is a test',
> X-Silly-Header => 'asdfasdf',
> Message => 'This is the body of my message blah blah blah'
> sendmail %mail or die $Mail::Sendmail::error;
> CPAN is your friend. :)