Posts Tagged ‘form’

Disable Form Autocomplete

Disabling a visitor’s browser’s built-in form autocomplete feature sounds like it should be a simple enough task, but like many seemingly mundane things in web design it’s a bit asinine. I have personally never had to do this until yesterday when I made an AJAX-based autocompleting search field and realized it didn’t do much good hiding behind the browser’s. It could also be useful to avert the visitor’s autocomplete where the data shouldn’t be remembered by the browser (like credit card numbers) or re-entered for verification (like e-mail addresses).

The easiest method (and the one with which I went) is to add the

autocomplete="off"

attribute to your <form> or individual <input> tags. According to Mozilla Developer Network’s How to Turn Off Form Autocompletion:

This form attribute was first introduced in Microsoft’s Internet Explorer 5. Netscape introduced it in version 6.2 — in prior versions, this attribute is ignored. The autocomplete attribute was added at the insistance of banks and card issuers, but prior to HTML5 was never part of an official standard.

In practical terms this means the autocomplete attribute is perfectly valid and there is no good reason you shouldn’t use it. In ideological terms, unless you are using it in an HTML5 document, the attribute is not valid HTML and will fail a validation test.

Sometimes it’s OK to be a rebel. Sometimes there’s a cheat code, though. It’s possible to set this attribute in JavaScript and produce flawless HTML. There is only one drawback: those with JavaScript disabled (no one) will not be affected:

var q = document.getElementById('query');
q.autocomplete = 'off';

An alternative I thought of but rejected on the grounds that it would make untidy URLs is the use of hidden <input>s and the onchange event handler. It could work well for POSTed forms, however:

<input type="hidden" name="query" id="query">
<input type="text" name="<?php echo md5(time()); ?>" onchange="document.getElementById('query').value = this.value;">

max_input_fields: Why Your Long Forms are Being Chopped Off

If you don’t keep your php.ini in sync with your PHP version you might be wondering why very large forms seem to be missing their bottom half when you go to analyse your $_POST array. Newer releases of PHP have a configuration directive called max_input_fields with a default value of 1000 which is meant to help reduce the risk of DoS.

I’ve seen it argued that forms with over 1000 fields can probably be organised a better way, and that’s mostly true – but what happens when your software is a dynamically generated spreadsheet a la CSV verification and pre-processing?

You might want to take this as a cue to update your php.ini but it’s also safe to drop

max_input_fields = 40960

or some other number reasonably tuned to your needs into your existing config.

Brute Force and Flood Protection for Web Forms

In the last article I told you any username-and-password authentication system that is exposed to the Internet is inherently vulnerable to dictionary and brute force attack. If you must use such an authentication scheme you can defend it by implementing rate control. If you block an attacker from trying to log in for one hour after three failed attempts it would take them a year to try just under 3,000 combinations. In cryptanalytic terms that is abysmal and the odds are on your side that the attacker will have moved on by then.

While porting your ban system to fail2ban might be a great idea it’s probably overkill for situations where you have hundreds of legitimate users who might often forget their credentials; IP-bans are not generally considered good customer service. Many sites, including Google, will present the user with a CAPTCHA after three failed attempts and that’s great but those are getting easier to crack every day.

For the sake of the pseudocode in this article we’re going to assume you want to block the  potential attacker and politely tell them they have either a) failed to log in too many times, please come back in an hour or b) posted too recently, please try again. Since we want to be able to rate control two (and perhaps more in the future) different things and we don’t want to make a mess of our database let’s make one table called ‘greylist’ and use the type column to differentiate:

CREATE TABLE `demo_cat`.`greylist` (
`type` VARCHAR( 30 ) NOT NULL ,
`date` INT NOT NULL ,
`ip` VARCHAR( 15 ) NOT NULL ,
PRIMARY KEY ( `ip` ) ,
INDEX ( `date` )
);

Now in your login script for argument’s sake we’ll say $outcome is a boolean representation of if the authentication was successful or not and $delay is the period of time we want to measure for in seconds. We’ll start off by clearing everything that’s out of date, a relatively inexpensive query to run every time there’s a failure. After the table has been updated we’ll add an entry for the current failure and take a tally of all the entries for the user’s IP. If the tally exceeds the retry $threshold we’ll tell them to buzz off for an hour, change their password, show a captcha or whatever suits your site best.

<?php

if(!$outcome)
{
   $ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
   mysql_query("delete from `greylist` where `type` = 'login' and `date` < '".time()-$offset."'");
   mysql_query("insert into `greylist` (`type`, `date`, `ip`) values ('login', '".time()."', '$ip'')");
   $result = mysql_query("select `ip` from `greylist` where `type` = 'login' and `ip` = '$ip'");
   if(mysql_num_rows($result > $threshold))
   {
      // Too many tries, what now?
   }
   else
   {
      // Please try again
   }
}

?>

It is as simple as that. Now let’s use this to flood-protect our comments box:

<?php

if($_POST)
{
   $ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
   mysql_query("delete from `greylist` where `type` = 'comment' and `date` < '".time()-$offset."'");
   mysql_query("insert into `greylist` (`type`, `date`, `ip`) values ('comment', '".time()."', '$ip'')");
   $result = mysql_query("select `ip` from `greylist` where `type` = 'comment' and `ip` = '$ip'");
   if(mysql_num_rows($result > $threshold))
   {
      // You posted too recently, please wait x seconds before trying again.
   }
   else
   {
      // Continue...
   }
}

?>

A more sophisticated implementation of this concept is in use at Ychan, where users’ posting patterns are analyzed to determine if they are computers, legitimate humans or computers trying to look like humans.

Return top
foxpa.ws
Online Marketing Toplist
Internet
Technology Blogs - Blog Rankings

Internet Blogs - BlogCatalog Blog Directory

Technology blogs
Bad Karma Networks

Please Donate!


Made in Canada  •  There's a fox in the Gibson!  •  2010-12