Archive for cgi scripts

protecting email forms

Captcha

Ever had a mail/contact script hacked? There’s a couple of ways to avoid this problem. One of my favorites is to use some type of captcha program. There are several considerations though. Some of these programs can distort the image to the point where I have trouble reading it. And of course, for the visually impaired, this is a bit much (although it’s nice to see that Blogger added an audio alternative recently to their captcha script). I chose to use THaCAA - Telling Humans and Computers Apart Automatically for my latest mail script because it sidestepped some of these issues altogether (it can be seen here) and it is written in php.

I’ve been pretty pleased with this one. I particularly like that it’s text based. There’s nothing wrong with my vision, but half the time with the more typical captcha modules, I can’t make out what the squiggles are. Of course, any non-English speakers may be out of luck, but since I’m writing this in English, it’s reasonable for me.

While no captcha script is uncrackable, by any means, it seems to have been sufficient to stop the ones I’ve gotten here in their tracks. I haven’t had my other security checks (which come into play if anything gets past the captcha query) triggered so far, knock on wood. In other words, captcha makes a very good front line defense.

Installing this particular program was quite easy, following the given instructions. Once it has been unpacked into a directory on the website, then I modified my mail.php script as follows:

First, include the functions and such:


<?php
  global $textTHaCAA_datalocation;
  $textTHaCAA_datalocation='textTHaCAA/THaCAAdata';
  require_once('textTHaCAA/textTHaCAA.php');
?>

along the top of the file. Now, within the mail <form section:


<?php textTHaCAA_ask(); ?>

and then in the form response (amongst all other applicable checks):


<?php if (textTHaCAA_answer() && textTHaCAA_hasrun()) : ?>

If it passes the above checks (plus all the other requirements I have of other form data plus security requirements), then I send the email. It couldn’t have been easier to integrate (other than the nearly unrememberable acronym itself, but that’s what cut and paste is for ;-) ). I also liked how it integrated cleanly with the page layout itself, it makes no assumptions about sizes, colours, fonts, and so on. Big thumbs up.

General security tips

Besides that, there are some standard ways to avoid problems that a malicious human (as opposed to a ‘bot that can’t get past the captcha) might still present. Here are several tactics:

  1. Check the host domain name and ensure that it’s from the same domain the mail script is at. E.g., my script checks that the originating form is from k9web and not some other machine.
  2. Force the mail script to accept only POST style connections and not GET. GET potentially lets the hacker alter the variables in the URL itself. In general, no form variable that is of a sensitive nature should be modifiable this way; in my mail scripts I disallow it altogether.
  3. Accept connections only from browsers and not other agents.
  4. Check all given form values for anything suspicious. This could include mail headers (that would never be part of a general text message being sent as email) such as content type, cc, bbc, and so on.
  5. Exclude also any type of commands that might be remotely executed depending on your server. For example, because I’m on a unix server, one of the things I check for and disable is anything that looks like an attempt at a shell escape.
  6. Exclude or disable (I often simply strip out) any html in the variables. Or allow a small subset (italics, bold, blockquote) and exclude the rest.
  7. Check for issues particular to the language you’re writing the script in. For example if I’m running a perl script I will strip out any backticks appearing in values because those are used to execute perl commands within them.

Resources

General faq on security. This document is starting to show its age (last updated 2002) but the general concepts and such laid out here are still very relevant and make a good starting point.

Specific tips for protecting mail forms written in php. Step by step example with php code supplied.

Specific tips for protecting forms written in perl. Step by step examples.

General tips on protecting web forms. This may be perl-oriented but it also has excellent general suggestions for any script writer to pay attention to plus links to other resources.

del.icio.us:protecting email forms  digg:protecting email forms

Comments (1)

rethinking form/post conventions

Ever since I first started scripting cgi to process forms I’ve used the two file format: the first file puts up the form and such and calls the second file to process the results of the form.

But it really doesn’t have to be like that. At work, I have a single program that lets you search through our database and display things, setting options and so on, and paging through the results. It only uses one executable (well there are a few more, but each one encapsulates a certain kind of function and as long as you’re doing that, you stay within that executable). Now admittedly I’ve torn my hair out more than once debugging this thing, so this idea can go too far in the other direction, but keep it to simple pairs of form/post and I’m liking it.

So I’ve started looking at my old sites and in particular the old one of mine that was offline for six years and rethinking how I did this stuff. And I’m thinking the single file form/post is a much better way to go. It’s fewer files for one thing. I’m not left having to grep through the file to see what it calls to trace down problems. They’re all there in one spot.

So for example I just redid the mail form which started out in mail.php that called sendemail.php (that’s another thing, it simplifies naming conventions — at another site of mine I’ve been trying to standardize to action_form.cgi and action_post.cgi but still it’s all a mess.

But this comes out nice and slick in one file. Start up the headers, check whether it’s a submit and the form goes in the first half the if statement, the post in the second half. Close off with the footers and it’s all set.

Now, let’s see, just how many more files are lurking around on this site? Sigh…

del.icio.us:rethinking form/post conventions  digg:rethinking form/post conventions

Comments (1)

forays into local cpan installation

I really dislike having to install perl modules locally. But sometimes that’s the set of cards I get dealt. And in all honesty, once it’s properly set up in an account, it’s easy to add on any others at a later date. So. I generally start with a local perl directory, in $HOME/perl, to keep things tidy. Otherwise I wind up with a more generic bin and lib sitting out there, and there’s lots that use bin & lib that have nothing to do with perl.

I add env variables:

if [ -d $HOME/perl/lib/perl5 ]; then
        PERL5LIB=${PERL5LIB:+$PERL5LIB:}$HOME/perl/lib/perl5
fi
MANPATH=${MANPATH:+$MANPATH:}$HOME/perl/share/man
export MANPATH PERL5LIB

(or if you prefer csh style — which I do, but I haven’t bothered to switch these bash shells around yet — I may, if I get irritated enough)

setenv PERL5LIB      $PERL5LIB:$HOME/perl/lib/perl5
setenv MANPATH     $MANPATH:$HOME/perl/share    

You can use printenv in most shells to double check the settings and make sure they “stuck”.

There really doesn’t seem to be any one place that combines all the info I use for a local install. I usually start out with this one which is almost complete but it leaves out salient details such as exactly how to start up cpan (which I always forget, it has such forgettable syntax) and doesn’t really contain tips for troubleshooting (there’s always troubleshooting).

However, it provides a perfect MyConfig.pm file to get started with, so I copy that into the ~/.cpan/CPAN/MyConfig.pm and follow the instructions it has in the comment section at the top. After the localizing alterations, I can run perl -c MyConfig.pm in order to make sure I haven’t done something boneheaded.

Now I’m ready to rock and roll. Get into cpan via perl -MCPAN -e 'shell' and now I can start installing. The help file I listed before suggests checking the changes I make to MyConfig.pm via a make on Text::Autoformat. I don’t really bother anymore but it’s a handy way to check that the variables are all correct.

Let’s say I want to install Flickr’s API. So I go with install Flickr::API. It will ask me some questions. What I have found out about CPAN is that most of the time (as in 99% of the time), the default is a perfectly good way to go when it asks questions. Quite often when I install something, it will suggest other things that should be installed or updated, etc. I just go with the flow on all that.

When I nibble around this article you’ll see more tips and such on unprivileged perl installs. Obviously installing your entire local copy of perl isn’t the way to go for the most part (and neither am I actually trying to install Bugzilla, at least not in this little essay), and they discuss a slightly different way of setting up the MyConfig.pm file, but there’s other goodies such as force install which I can try if I get nasty messages after attempting a plain install. Also what frequently helps me is to try installing the noted dependency packages on their own. Take the Flickr::API — it also wants XML:: Parser::Lite::Tree:: XPath and will inform me of that while installing the Flickr stuff. And sometimes it will take care of it, and sometimes it won’t; doing a separate install on that often works.

The last bugaboo I generally wind up dealing with, especially since I mostly write perl for cgi scripts is the transition from running on the command line to calling it from a web page. All the previously mentioned steps get the perl working on the command line, but then it can still turn into a big ol’ Internal Server Error mess when I try to go online.

The problem is, of course, that the http client isn’t accessing my pretty MANPATH and PERL5LIB paths for the extra info. This is where tweaking the @INC array helps: I can be all perl hacky and do something like BEGIN{unshift @INC, "$HOME/perl/lib/perl5"} (note that $HOME itself won’t actually work here, I use it for shorthand notation — replace this with the full value of $HOME in this case). But I just discovered this tidbit when googling and trying the use "$HOME/perl/lib/perl5"; worked like a charm! I’ve posted this previously only at another location: the flickr slideshow. Because www.sclrr.org is on a different server than is www.io.com/~sclrr, I had to re-install the perl libraries, and find a different solution to the path problem.

del.icio.us:forays into local cpan installation  digg:forays into local cpan installation

Comments (1)

Bad Behavior has blocked 953 access attempts in the last 7 days.