Archive for php

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)

detouring css through php

One thing that tends to drive me nuts when putting a css file together is repetition of the colours. CSS has no mechanism to define constants or variables and it can be pretty tiresome playing around with resetting the colours and such when tweaking a web page.

So I made mine into a php file. There’s a few tricks, but it’s very straightforward. First, you call it in your main html file (or output) as with any other css file, only with it’s name:


<link rel="stylesheet" href="k9web-css.php" type="text/css" media="screen" />

Now here’s the fun part. The first line in the php file must now be:


<?php header("Content-type: text/css");
/* this tells the browser this is a css file! */
?>

Otherwise the file is sent as text/html and I get unhappy junk printed out. With that out of the way, the top of the file can contain something like this:


<?php
/* define colours, etc here */
$darkgrey="#555";
$lightgrey="#ccc";
$offwhite="#f6f6f6";
$cream="#ffffe7";
$brightred="#ff0000";
$darkred="#aa0000";

/* change these to change color scheme */
$bgcolor=$cream;
$fontcolor=$darkgrey;
$linkcolor=$darkred;
$hoverlinkcolor=$brightred;
?>

Now I proceed with the rest of the css definitions as usual, but when I want to use a defintion, I pop it in like this:


a:hover {
        color: <?php echo $hoverlinkcolor ?>;
        text-decoration: underline;
}

Looks like someone else (actually many people; try googling on “variables in css”) was addressing the same problem. My solution is pretty straightforward, although it does require access to php, etc. This solution hides it but amounts to using php to parse and replace behind the scenes, so I think my solution is at least more direct…

del.icio.us:detouring css through php  digg:detouring css through php

Comments (4)

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)

the horror that is MSIE 6

I know this is a bad browser. But when I’m on the user end, it’s easy enough to ignore, especially when I use Firefox or Opera or even Konqueror. However on the web author side, it really makes me tear my hair out. And I just found a beaut of a bug, where it doesn’t like plaintext http in certain situations. I played around with it for a while, and finally just excluded the call to the plugin based on browsers. So, if you’re reading this with MSIE 6, you are not seeing the recent comments in the sidebar. (And if you’ve got XPSP2 and/or plan to upgrade to Vista, definitely snag IE7. I’ve been pleasantly surprised with how many standards compliance issues they actually fixed…)

My coworker isn’t very helpful: telling me I should put in an activex control that shuts down IE6 if someone tries to open DR in it :-D Oh, the temptation…

del.icio.us:the horror that is MSIE 6  digg:the horror that is MSIE 6

Comments

a mountain out of allow_url_fopen

It seems that DreamHost has disabled this option. What is it? Good question. From the online PHP manual,

This option enables the URL-aware fopen wrappers that enable accessing URL object like files. Default wrappers are provided for the access of remote files using the ftp or http protocol, some extensions like zlib may register additional wrappers.

What are the security issues with allowing url’s to be openable in a PHP script? Well some of them are pretty hair raising and there’s a excellent overview of the problems with allowing urls to be opened in PHP programs. So that’s all well and good. I appreciate the fact that DreamHost takes steps to put together a secure hosting system.

And as a side note, my hair’s still standing on end with the way PHP allows some of this stuff. Granted, you get security issues in Perl, especially if you’re going to shovel userinput through system calls, or even sometimes just blatting stuff into email messages. But there’s convenient utilities to sanitize such input, plus judicous ways to call the system function to foil such attacks. But this url thing, especially the way it can be used to trick a site into including and running a remote file… :-O The one that really blows my wig back is where the file name is garnered from the GET url, so that you could change, just by typing on your own browser to attack, http://example.com?goodfile.php to http://example.com?badfile.php and just sit back and watch the mayhem unfold.

Goodness gracious.

But let’s zoom back to that DreamHost Wiki document for a second. Reading through it, one gets the impression that include is on the no-no list. Oh, and require is mentioned at the very last moment too. At a guess, I’d say fopen was also verboten, though that’s not mentioned here. So we’re left with a bit of mystery as far as the process of de-allow_url_fopen-ing goes.

Codesnippet is one of the plugins that’s creating my mysterious error message, so I grep thru all of its files for instances of the include or require calls. I don’t find either, but I do find require_once and at a guess, I’d say it’s on the shit list too. Hmmm.

So I google for more info on allow_url_fopen and it’s astonishing how little info there is.

OK, let’s recap. Basically, you can’t specify url’s to a set of functions that take url’s as arguments. So far I have: and fopen.

One method for bypassing the problem is to specify the file in such a way it’s no longer an url. The important thing to remember is that this property holds in a case like this:


require_once('/home/coolblog/www.urlname.com/blog/wp-config.php');

If you can connect to blog with http://urlname.com/blog/), then it’s a url, even though you don’t have the http prefix. As DreamHost’s Wiki entry notes, you can fix the problem like this:


require_once($_SERVER['DOCUMENT_ROOT'].'/blog/wp-config.php');

But there are more complex cases out there, that require cURL to solve. Wandering over to that page we immediately notice this example


<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);
c u r l _ e x e c($ch);
curl_close($ch);

given for fetching a web page. Also, there appear to be some new candidates for the “shit list” here: file_get_contents(), and file(). Is this list complete? I don’t know for sure. CURL, Client URL Library Functions is actually a pretty interesting wrapper, especially if you scroll down the page and peruse the commentary.

As a postscript, in case you were wondering why c u r l _ e x e c was written that way, well so am I. If I don’t break it up, I can’t save this post! I’m guessing some kind of hyperactive filter checking for cruft in here? Even though it’s not going to be executed here, etc. It took me quite some time to figure out what was going on, the message I kept getting was

Service Temporarily Unavailable
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.

So I saved off the file locally and left it alone for the rest of the night, even though I couldn’t find anything in the status logs. But later on, I wound up creating a new post, and then, believing that all was well, returned to this post and got stonewalled again…So I went back and put in one line at a time to find out where the problem was…Aiee…

In any case, I have some questions into Dreamhost I’m waiting on, so I’ll go ahead and publish this. But I’d like to get together sort of a conversion kit that’s a bit more comprehensive than the information I found.

del.icio.us:a mountain out of allow_url_fopen  digg:a mountain out of allow_url_fopen

Comments (2)

« Previous entries Next Page » Next Page »

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