views:

455

answers:

9

Is there a good method of form security that does not involve CAPTCHA? CAPTCHA is so annoying, but I need security because I am getting form spam. My form is PHP.

A: 

Math questions are interesting alternative. You can even write your own simple math checker by using random numbers.

Here are couple of plugins:

http://www.codegravity.com/projects/mathguard

http://sw-guide.de/wordpress/plugins/math-comment-spam-protection/

Ivo Sabev
Good links, but the kind of math questions that a human can solve, but a computer can't, is very limited to ivory tower maths IMO.
Chris Lercher
Sure but spam bots are not expecting to solve math questions, which is the idea behind. Also about a simple contact form this is enough to restrict the most popular spam bots, since noone will put effort and processing time in spamming small website. Also I liked the idea of showing pictures of animals shown below with the KittenAuth
Ivo Sabev
@Ivo: Math problems are a temporary solution, since people do improve spambots to defeat common defenses. Also, any system that shows ten animals and asks which is the kitten will be penetrated one-tenth of the time by random chance, and any botnet will have no problem making ten times the probes on a given website.
David Thornley
@David if you are securing the Pentagon indeed. If you are securing Mr Noone's contact form I don't think so. Solutions are context based.
Ivo Sabev
This is a very weak capthca, the author doesn't want to use capthcas.
Rook
+7  A: 

Try askimet. It's great at flagging spam. The API is easy to use and completely transparent to your users.

John Conde
+1 Congratulations this is the only valid answer thus far.
Rook
To be fair, he didn't ask for free.
Joe
+18  A: 

Here's what I've found to be very effective (and dead simple):

  1. Put a hidden field on your form. Give it a name like "phone" or something similar/common and put in a default junk value.

  2. Put another regular text input field on your form, but hide it with CSS. Make that one empty. Again, give it a "real" sounding name (first_name, phone_number, whatever).

  3. When the form is posted, verify that the hidden field still has the default value and the field you hid with CSS is still empty.

You're basicly taking advantage of the fact that most spam bots will simply fill in every field in the form in order to avoid failing any required field validation checks. Some might be smart enough to ignore hidden fields, but I've never seen one that was smart enough to ignore fields hidden with CSS.

ETA: To address some comments - Is this a truly "secure" system? no, it certainly isn't. It would be trivially broken by anybody who wanted to specifically target your site. That said, it is still remarkably effective against the automated form spamming bots that most "low value" sites will see.

If you want to stop a determined attacker, you'll need something a bit more invasive. Another poster mentioned Akismet, which is a good option. Re-Captcha would be another. Stopping determined, targeted spammers is hard though. Even Yahoo and Google have a hard time with it.

Eric Petroelje
This is the best solution I've found, but it doesn't protect against "Mechanical Turk" spam where people are paid a few cents for every message they post on a blog article
Gareth
@Gareth if its people doing to the spamming, captchas wouldn't stop them either.
CrazyJugglerDrummer
+1 Great idea. It would prevent spam from general bots, but would do nothing for someone who wants to specifically spam you. For example, if you have a registration form and don't want auto-generated registrations, this won't help you. Someone just needs to sniff the http traffic through firebug or something similar.
sri
@sri - exactly, if your site is big enough that people will target it specifically (as opposed to typical drive-by bot spamming) you would need something more sophisticated. But this will probably do the trick for better than 90% of websites.
Eric Petroelje
-1 security in obscurity. Further more i have no idea what attack bot you are referring to.
Rook
@The Rook: Security by obscurity isn't bad per se. It can be a useful layer to add a bit more work to an attack, and for low-value applications it may be all that's needed. What's wrong with it is that its effect is very easily overestimated, particularly by the incompetent.
David Thornley
@David Thornley I completely disagree. This system will take no more than 4 minutes to break. I don't believe in secuirty though obscurity (http://en.wikipedia.org/wiki/Security_through_obscurity), its not a methodology that stops attacks. (Which is a throw back to our Boolean vs float debate)
Rook
There is a bigger issue here, what exactly is he trying to defend against? Because its **not** stopping people from brute forcing a login prompt or sending a ton of email from a "Contact Us" form.
Rook
@The Rook: The system will take only moments to break, if somebody actually decides to break it. If this is form spam that's just scattered to any website it can find, it's likely to be foiled by this, at least for a while. If anybody looks at the site and thinks "I want to spam this one," this approach is useless.
David Thornley
I have thought about this a bit more and it probably will stop a spam spider. However, if this became wide spread it would be broken immediately.
Rook
@Rook: Most of the answers given (including mine), can be broken in mere minutes. **Practically speaking** nobody is going to make the effort to do so, until, as you point out, the technique becomes widespread.
Dave Jarvis
A: 

Depends on the type of form spam, general bots made for spamming any form it finds can easily be foiled by a lot less obstructive measures (like "what is the name of this site?"), but if someone has made a bot targeting your site specifically you will need captchas or something equally annoying.

eBusiness
A: 

If all you are doing is avoiding spam bots (automated programs that seek <form> tags, fill in all <input> fields, then submit the form), then a simple solution is to do as Paolo said: use JavaScript to add a hidden field. The disadvantage is for people who disable JavaScript.

Feel free to use this:

<form method="post" action="contact.php" id="commentForm">
  <label for="name">Name</label>
  <input type="text" name="name" id="name" maxlength="64" /><br />

  <label for="email">Email</label>
  <input type="text" name="email" id="email" maxlength="320" /><br />

  <label for="message">Message</label>
  <textarea name="message" rows="10" cols="40" id="Message"></textarea><br />

  <label for="human">40 + 2 =</label>
  <input type="text" name="human" id="human" size="10" maxlength="3" /><br />

  <p align="center">
  <input type="submit" name="submit" value="Send" class="submit-button" />
  </p>
</form>

Then place the following as "contact.php" in the same directory:

<?php
require_once 'lib/swift_required.php';

// Reason for not contacting.
//
$reason = 'default';

error_reporting( 0 );
ini_set( 'display_errors', 0 );

function not_contacted() {
  global $reason;

  header( 'Location: error.html' );
}

function wms_error_handler($errno, $errstr, $errfile, $errline) {
  not_contacted();
  return true;
}

function wms_shutdown() {
  if( is_null( $e = error_get_last() ) === false ) {
    not_contacted();
  }
}

set_error_handler( "wms_error_handler" );
register_shutdown_function( 'wms_shutdown' );

$name = trim( $_POST["name"] );
$email = trim( $_POST["email"] );
$message = trim( $_POST["message"] );
$human = trim( $_POST["human"] );
$subject = 'FormSpam';
$contacted = false;

if( is_null( $name ) || empty( $name ) ) {
  $reason = 'name';
  $human = false;
}
else if( is_null( $email ) || empty( $email ) ) {
  $reason = 'email';
  $human = false;
}
else if( is_null( $message ) || empty( $message ) ) {
  $reason = 'message';
  $human = false;
}
else if( is_null( $human ) || empty( $human ) || $human !== '42' ) {
  $reason = 'computer';
  $human = false;
}

if( $human === '42' ) {
  $subject = 'YourCustomSubject - '.$name;

  $transport = Swift_SmtpTransport::newInstance( 'localhost', 25 );
  $mailer = Swift_Mailer::newInstance( $transport );

  $message = stripslashes( $message );

  $message = Swift_Message::newInstance()
    ->setSubject( $subject )
    ->setFrom( array( $email => $name ) )
    ->setTo( array( 'YourEmailAddress' => 'Your Name' ) )
    ->setPriority( 1 )
    ->setBody( $message )
  ;

  if( $mailer->send( $message ) ) {
    header( 'Location: contacted.html' );
    $contacted = true;
  }
}

if( $contacted === false ) {
  not_contacted();
}
?>

Should prevent 99% of spam.

I have not added constants, but I'm sure you can figure out where to change the script. I've removed the part where it redirects to different pages depending on what was (or was not) entered by the user (e.g., missing full name, e-mail address, message, and such). If you want a full version of the script, let me know and I'll fix the code to be more new-developer-friendly.

Note the Swift Mailer dependency.

Dave Jarvis
-1 security though obscurity. What exactly are you trying to defend against? You have to better understand the threats you face.
Rook
@Rook. The original post said "getting too much spam". This is a *practical* solution to spam. Yes, it is trivial to break, but I doubt spammers will waste their time trying to codify a hack to submit information against this site's form. Also, if you would like to suggest some other solutions, in addition to voting everyone down, that would be great.
Dave Jarvis
+4  A: 

This kind of validator is cute and quick!

CAT BOX

Obviously, you will want to display one of a many possible animal images, and the list should be randomized as well.

I understand it will only work X% of the tim, but adding more options to the list will help reduce spam.

macek
This is a captcha.
Rook
@The Rook, not in the hair-pulling, scream-at-your-computer, type-in-all-the-swirly-obfuscated-letters sense.
macek
@smotchkkiss: +1 for sneaking in the FSM
Chris Lercher
I suppose its nice if you want to trip over http://www.direct.gov.uk/en/DisabledPeople/RightsAndObligations/DisabilityRights/DG_4001068
David Dorward
@David Dorward, I suppose it's nice if you like cats.
macek
A: 

If the time to submit the form was inhumanly fast, then it likely was not a human.

Dave Jarvis
A: 

Consider Greylisting.

Dave Jarvis
A: 

I have already worked something similar.

  1. When you open a form generate one md5() string and put it in session (for example $_SESSION['captha'])
  2. Your form sould have one hidden field and when you open this form write this data from $_SESSION['captha'] into this hidden field
  3. When you receive this post request compare value in session and value which come with this hidden field. If it is same everithing is ok and vice versa. Of course, after you handle this request just delete variable $_SESSION['captha'].

This work for me.

Milos