From: Markus Date: 2004-10-26T00:51:19+09:00 Subject: Re: Poor Man's CAPTCHA (was Re: Garden Spam) Here's my 9 Colons (that would be two cents--but my heart is still in Costa Rica): Multiple small, partial fixes will work better than one uber-defense, especially if they are complementary. The problem with fix-it-for-all-time monoliths is that if they fall you are back to square one. If there are lots of little things each of which is different it is easier for the good guys (more modular) and harder for the bad guys (make _them_ play whack-a-mole for a change). -- Markus On Mon, 2004-10-25 at 08:35, Jamis Buck wrote: > Austin Ziegler wrote: > > On Mon, 25 Oct 2004 02:24:51 +0900, Jamis Buck wrote: > > > > > >>I've got a PMC (poor man's captcha) that guards the comment submission > >>for my blog (http://www.jamisbuck.org/jamis, and click a 'comment' link > >>to see it). It's just plain text that must be entered backwards in a > >>text box. Easily circumvented, 'tis true, but I haven't had a single > >>spam comment on my blog since I implemented it. > > > > > > Jamis, > > > > What did you use to do that captcha? That captcha I might actually > > support using; I just don't want to do an image-based captcha because > > of accessibility issues. > > > > -austin > > Just Ruby. In my blog-comments.rb file, I've got a method 'captcha' that > returns the captcha block as HTML, expecting to be wrapped in a form: > > def captcha > source = "23456789abdefghijkmnpqr" + > "stuvwxyzABDEFGHJKLMNPQR" + > "STUVWXYZ!?%\#@&*:\"<>".split(//) > source = source.sort_by { rand } > chars = (1..10).collect { source.shift } > > string = chars.join > md5hash = MD5.hexdigest( string ) > > captcha_string = chars.reverse.collect { |i| > "#{i} " }.join > > <<-EOF >

> Type the following characters in reverse > order into the text box. Spaces are optional. >

>
> #{captcha_string} >
> > What characters did you see: > > EOF > end > > Then, when the form is submitted, I call 'validate_captcha': > > def validate_captcha > checksum = @session['checksum'] > captcha = @session['captcha'] > sum = MD5.hexdigest( captcha.gsub(/\s/,"") ) > > sum == checksum > end > > If this returns true, they entered the captcha string correctly. Like I > said, it's pretty simple, and easily circumvented, but it's worked well > for me so far. > > (The above code is in the public domain, so do with it as you will.)