Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Gracious Monks of the Monastery!

I'm working on a simple newsletter script that receives email addresses from a form and stores them in a file. Here is what I have so far:

#!/usr/bin/perl -wT use strict; use CGI; use Email::Valid; # retrieve form parameter(s) my $q = new CGI; my $tainted_email = $q->param("email"); # check that $tainted_email is valid my $is_valid = Email::Valid->address('$tainted_email'); # if $tainted_email is valid, store the address in $email my $email = ""; if ($is_valid) { $email = $tainted_email; } # grab user information my $ip_address = $ENV{REMOTE_ADDR}; my $referrer = $ENV{HTTP_REFERER}; if ($email) { # store the data in a plain text file open LOG, ">>newsletter.txt" or die "Cannot Access Logfile: $!" print LOG "$email : $ip_address : $referrer\n"; close LOG; } # print thank-you page

The checks based on whether or not $tainted_email is valid seem rather messy to me. My primary concern is validating all the parameters that aren't sent to the script, including the IP address and the referrer. I want to ensure they're of valid structure, and of valid length. I'm also looking for a simple-as-possible storage mechanism for them (escaping issues?).

Also - I don't have access to httpd.conf but I'd like to ensure no one can read the files the info is stored in. Is there a simple way to do this (ie file permissions? I'm not sure what user the webserver is running as), or do I have to have .htaccess files enabled? Thank you for your time :)

Replies are listed 'Best First'.
Re: Subscription form script
by tcf22 (Priest) on Aug 06, 2003 at 12:12 UTC
    You could use CGI::Validate to validate your form entries, although your current method is good too.

    For validating ip_address and referrer, you could use this
    $q->param('ip_address', $ENV{REMOTE_ADDR}); $q->param('referrer', $ENV{HTTP_REFERER});
    to set the CGI parameters, then use CGI::Validate.

    As for securing the files, why not just write 'newsletter.txt' outside the root of the webserver.

      As for securing the files, why not just write 'newsletter.txt' outside the root of the webserver.

      Because on this server I don't have access anywhere else. I have a feeling that any other solution will be sub-optimal so I'll probably just switch hosting plans unless anyone has a bright idea.

      Thanks for the CGI::Validate link, I'll check it out :)

        I know on my apache server, any files that start with .ht (/^\.ht/) are filtered and never served out. If this is the case on your server perhaps .htnewsletter would work. Just a thought.
Re: Subscription form script
by bobn (Chaplain) on Aug 06, 2003 at 13:21 UTC

    $ENV{REMOTE_ADDR} is supplied from the TCP connection by your webserver and is unlikely to be wrong (unless you've mucked with it elsewhere).

    --Bob Niederman, http://bob-n.com

      It could be spoofed though, but I guess there's no simple way to validate that.

      What I intended to use it for was to check how many times a specific ip had accessed the script to prevent flooding. I'm probably being overparanoid here and will just end up blocking some proxies - what do you think?

Re: Subscription form script
by waswas-fng (Curate) on Aug 06, 2003 at 14:26 UTC
    My primary concern is validating all the parameters that aren't sent to the script, including the IP address and the referrer. The referrer is easily changed client side, sometimes not sent at all (proxies, web browsers, whatever don't have to send it). Think of it as tainted client supplied data (as if from your form) trust it and act on it about as much as a non required unverifyable field on your form.

    -Waswas
      My primary concern is validating all the parameters that aren't sent to the script, including the IP address and the referrer.

      Sorry, I meant s/aren't/are/;

      So, my primary concern is validating all input from the client, including the IP and referrer. I think we're basically saying the same thing although I can't type todya ;-)

        My point is you can't validate the referrer. It is an untrusted string that can be hand set to anything the client wants (or not set at all). Meaning if you are going to say, only show this page when the referrer is set to http://www.page_i_want_you_to_come_from.com/here.html and the source IP is 10.128.1.1, you must note that even though referrer is saying it is from http://www.page_i_want_you_to_come_from.com/here.html, it may not have actualy been there. Or even more doubious, if the referrrer is not set or not set to http://www.page_i_want_you_to_come_from.com/here.html the browser may still have come from that url. In short referrer is useless except for some very discountable logging tactics.

        -Waswas