http://www.perlmonks.org?node_id=546694

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

Yo.

I've got this script:
#! /usr/bin/perl -T use warnings; use strict; use CGI qw/:standard :cgi-lib/; my $q = CGI -> new(); my %user_data = $q -> Vars; unless (open( OUT, '>>comments.txt' )) { print $q->header( 'text/plain' ); print $q->p( "Error opening file: $!\n"); die $!; } foreach (sort keys %user_data) { print OUT substr($_, 1, 200),"\n"; print OUT "$user_data{$_}\n" } print OUT "========================================\n"; close OUT; print $q -> redirect ("http://www.kingdomadventures.org/form_thanks.ht +ml");
Attached to this form:
<form action="./cgi-bin/take_comments.cgi" method="post" name="W +riteUsForm"> Your Name:<br /><input name="1-From" type="text" size="35" /><br + /> Your E-Mail Address:<br /><input name="2-Sender's Email" type="t +ext" size="35" /><br /> Subject:<br /><input name="3-Subject" type="text" size="35" /><b +r /> Your message:<br /><textarea name="4-Message" cols="35" rows="7" +></textarea> <br> <input type="submit" value="Contact Us!" /> </form>

and some loser has been hitting it repeatedly with data like:
-From as5924@mysite.org -Sender as5924@mysite.org -Subject r Content-Type: multipart/alternative; boundary=56a225acf2431df137c24b08 +86bd3883 MIME-Version: 1.0 Subject: able bodied, two hundhred an tin pound, forty bcc: punk65@PunkAss.com This is a multi-part message in MIME format. --56a225acf2431df137c24b0886bd3883 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit of t. ames s finding themselves accidentally re assembled in --56a225acf2431df137c24b0886bd3883-- . -Message as5924@mysite.org

How can I protect myself?
Thanks!

Replies are listed 'Best First'.
Re: Some Loser is trying to spam MY script!?! What do I do?
by samtregar (Abbot) on May 01, 2006 at 17:47 UTC
    Validate your form input. Instead of just taking Vars and assuming it's right pass it through Data::FormValidator. You can go further after that - allowing only a certain number of hits per time period, per IP, for example - but you might not need to go to that trouble once you filter out clearly invalid data like this.

    Also, you need to do some locking on that file to prevent multiple simultaneous hits from corrupting it. I recommend you pick up a copy of O'Reilly's CGI Programming with Perl book. It will let you in on this and many other important techniques.

    -sam

Re: Some Loser is trying to spam MY script!?! What do I do?
by ruzam (Curate) on May 01, 2006 at 19:01 UTC
    The spammer believes you're using the comment form to send an email to somebody who cares (like a website administrator). They've inserted an extra \n into the subject, followed by their own mail message. Many (all?) mailers interpret the extra \n as the end of the first message and the start of a second message. So the spammer is attempting to use your comment form to send his own spam to the rest of the world. Since you're sending the comments to a file and not resending a mail message, the spammer is wasting is time (and your disk space).

    A good rule of thumb for anything email header related is to strip and ignore everthing after (and including) the first \n.

    You should probably be more descriminating with your acceptance of form variables. Blindly using everything in CGI->vars is likely going to bite you in the end.

      Another common variation used by spammers is to put the extra newline in a header field like Subject or From, and start the next line with the additional CC and BCC fields. Many feedback forms don't check every input line for extra newlines because the HTML Form is supposed to send only single line values there. The header fields are vulnerable too.

Re: Some Loser is trying to spam MY script!?! What do I do?
by polettix (Vicar) on May 02, 2006 at 08:40 UTC
    Altough not directly related to the particular problem, Ovid's CGI Course is an excellent source of inspiration for CGIs.

    Flavio
    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Don't fool yourself.
Re: Some Loser is trying to spam MY script!?! What do I do?
by leocharre (Priest) on May 04, 2006 at 15:39 UTC

    How about limiting the ammount of data sent, and then .. accepted?

    You can for one do the basic things.. which is.. in the html - set a limit to chars taken.. for example:

    ...m action="./cgi-bin/take_comments.cgi" method="post" name="WriteUsF +orm"> Your Name:<br /> <input name="1-From" type="text" size="35" maxlength="35"/><br /> Your E-Mail Address:<br /> <input name="2-Sender's Email" type="text" size="35" maxlength="35"/>< +br /> Subject:<br /><input name="3-Subject" type="text" size="50" maxlength +="50"/><br /> Your message:<br /> <textarea name="4-Message" cols="35" rows="7" maxlength="255"></textar +ea>

    This will prevent basic users from making some mistakes perhaps.. Now.. this limits *this* html snip from submitting more then a certain ammount of chars for some fields. But- for the real troubelmakers.. you do not know where the form data came from, so ... you use basic tools like javascript and html for limits, some syntax checking.. and basic stuff... like tellign the user with javascript alerts things like "you forgot to enter first name!" -- and that's all good. But your script taking the user input MUST assume the data awas sent from Hell by Satan Himself.

    That takes us to part two .. accepting the data received...

    #you got this.. foreach (sort keys %user_data) { print OUT substr($_, 1, 200),"\n"; print OUT "$user_data{$_}\n" }

    how about ...

    for (keys %user_data) { # basically just ripping some junk out $user_data{$_}=~s/[<>|\/\&\(\)\;\`]/ /g; } # and then... whatever you want.. foreach (sort keys %user_data) { print OUT substr($_, 1, 200),"\n"; print OUT "$user_data{$_}\n" }

    This is a loose hack .. that's all.. just strips out some junk. Very basic - just an example to give you an idea. For some real world stuff.. you should be predetermining every input variable that will be accepted.. and what it will contain!! use CGI::Validate - it's really nice.. you can tweak the heck out of it.. that is.. tell it what exactly you want each data field to have or not have,.. and how much to freak out if what happens.. like.. if extra fields are submitted.. ban the freaking ip and send a notice to the admin.. :) !
    I had some pain in the ass integrating it but.. it lets you do great things. If you want examples i can send you some.. of passing stuff to it... whatever.

    Be schizo about accepting form data. Be very very affraid. Always expect Satan is on his period.. and sitting at a shell prompt pinging your a55- and he's not using a browser to submit form data. Be parannoid.. and you will ultimately avoid a lot of *other* problems.. by being secure.. you avoid "mistakes".. security is not just about protecting from an attacker.. it's also protecting against mistakes and innocent erroneous data.. :) .. enough of me. Good luck. Take a look at CGI::Validate.

Re: Some Loser is trying to spam MY script!?! What do I do?
by bytex64 (Novice) on May 04, 2006 at 19:11 UTC
    I had this problem a while ago with a homegrown app. This may not work for you, but my solution was basically, "If the 'from' address states that it's from mysite.org, ignore it." Problem solved.

    The other suggestions about form validation and locking are arguably the better way to do it, though. :)