VileWorks

PHP Screencast: Hidden Captcha

As I was saying in a past–not so documented–article, this is how the Hidden Captcha concept works:

Does the user have JavaScript enabled?
If yes, they’re okay — let’em comment, no annoying captcha required.
No? We’ve got a suspect. Read them their rights and serve them the ultimate “are you human?” test.

I made this 5 minute screencast to earn fame and fortune on Nettuts, but I’m also posting it here along with some textual comments. Figured I’d make it easier for you to copy/paste the whole 2 lines of JavaScript.

Here’s what you start with, the source code from this tutorial.
(Note: be sure to have the Arial font file called arial.ttf in the fonts folder–copy it from your System in there because their archive does not come with it).

This is the JavaScript/PHP I’m pasting in:

<script type="text/javascript">
<!--	
	document.getElementsByName('code')[0].value = '<?php echo $string; ?>';
	document.getElementById('captcha').style.display = 'none';
 
-->
</script>

Both lines of JavaScript work on elements from this chunk of HTML:

<div id="captcha">
	<img src="captcha.php"/>
	<p><input type="text" name="code" /> Are you human?</p>
</div>

The first line of JavaScript sets the correct value for the code text field.
And the second line of JavaScript sets display:none to the captcha div, thus hiding it from anyone with JavaScript enabled.

Hidden Captcha instead of Akismet?

I use the same Hidden Captcha concept on this site, where I installed a modified version of the Simple Captcha WordPress plugin. But when you try to comment you don’t see any captcha requirement, do you? Not unless you have JavaScript disabled.

Since I’ve installed Simple Captcha, the Akismet spam count remained at 0 (zero).
And this leads me to the Akismet false positives issue. Where innocent comments can sometimes incorrectly show up as spam and get lost in the thousands of real spam comments.

How Spammers can play with Akismet system and get you banned?

Lets take an example of a blogger who wrote a harsh comment on other blogger’s website. Now the other blogger will take his identity (username, email and URL) and put them into a spam script (believe me there are plenty out there) and he will set the script to send out 100’s of comments/trackbacks to other blogs. Of course, most of these blog owners who got the ’spam’ would flag these comments as spam. This would result in your credentials being incorrectly marked as spam comments by hundreds of bloggers, thus ruining your expertise to promote your site.

You can read the rest of that article on Mind Tree.

Akismet is great and all, but man… I don’t want to send innocent people to the spam box.

So this Hidden Captcha system (easily implementable on any existing captcha system as seen in the screencast) can actually allow me to disable Akismet (thus eliminating the possibility of false positives) and keep actual spam comments away.
No usability issues because of hard to read captchas–for most of the readers.
And no accessability problems, because that small percent of humans without JavaScript enabled can still comment after filling in the Captcha code.


Link to the demo
–you can also check it out with JavaScript disabled, and have a look at its source code.

  • Share/Bookmark
9 Comments.

Liked it? Subscribe to RSS or receive updates via email:


9 Comments Comments RSS Trackback URL

  1. Gravatar Icon Stefan

    If you’re wondering why we had to move a part of the code

    Another thing we’re doing at the beginning of the screencast is moving the PHP code that generates the random string away from the file that outputs the image and into the page where the form is. Couldn’t we have just gotten it from the session using $_SESSION['rand_code']?

    Well, that wouldn’t have worked. If the random string would have still been in the captcha.php file (that’s the one that returns the image), then the string in the session would have always been one step behind the current string — because captcha.php is being accessed last, from the client, as an image and it would have generated a new random string.

    ReplyReply
  2. Gravatar Icon Bartek

    Nice idea, but there may be some issues about this solution.

    You are giving the right answer to the captcha right in your HTML code. OK, it may not be automatically found by standard spam bots but still it’s quite easy to find.

    I’m not saying it will not work, as it will be good enough as long as some spammer will write a bot to hack it.

    ReplyReply
  3. Gravatar Icon Stefan

    @Bartek: I know the answer’s in the HTML… But if anyone writes a bot that can find the answer (not very likely unless Hidden Captcha becomes as popular as Captcha itself, but still) it’s just a matter of changing the JavaScript around so that it does the same thing, but the code is written differently.

    ReplyReply
  4. Gravatar Icon Josh L

    Great idea. Regardless of effectiveness, to me the important thing is that people like yourself are creating alternatives, without which innovation is impossible.

    But Bartek does have a good point, which is that you are achieving something akin to security through obscurity. Your technique itself is not more secure (it is arguably not secure at all), the security comes from the fact that almost no one is going to write a comment bot for a single obscure website.

    Imagine that you’re immigrating along the Oregon Trail, and that your wagon has decoration which implies you are carrying gold. When bandits target such wagons, they simply set fire to the wagon then retrieve their spoils. What you have done is the equivalent of removing the decorations that suggest gold, so the bandits decide not to target you in the first place. But if they did decide to target you, your wagon is not any less susceptible to fire.

    ReplyReply
  5. Gravatar Icon Stefan

    @Josh L: Funny thing, I was talking in the article about Akismet’s false positives and how this would allow me to deactivate Akismet. But I haven’t actually deactivated it — until I saw 1 spam comment today: yours. Obviously a false positive.

    My Akismet plugin is now deactivated.

    Don’t call me obscure. You’re obscure.

    Kiddin’. Thanks for telling me about the Security through obscurity principle, didn’t know it actually had a name. And yes, to some degree, that’s what I’m doing.

    Here’s an example of how one could complicate the JavaScript to make it harder for a spam bot that can’t evaluate JS code to get to the secret string:

    secret  = '<?php echo $string[0]; ?>' + '<?php echo $string[1]; ?>';
    secret += '<?php echo $string[2]; ?>' + '<?php echo $string[3]; ?>';
    document.getElementsByName('code')[0].value = secret + '<?php echo $string[4]; ?>';
    

    instead of simply:

    document.getElementsByName('code')[0].value = '<?php echo $string; ?>';
    

    …Just adding to the obscurity.

    ReplyReply
  6. Gravatar Icon david

    If you base your idea on the fact that bots can’t execute javascript, the captcha is only needed for people who have javascript disabled. So if a bot has the ability to execute javascript it passes as a human while people with screenreaders and text only browsers will be marked as bots.

    I think you better use a sentence with basic math than a captcha. Or a link to a random audio file with the correct field input.

    If a bot can’t execute javascript why not remove the captcha input field? There is no need to give check the right value if you add the right value via javascript, is there? Just check if the field is present in the posted data or not.

    ReplyReply
  7. Gravatar Icon Stefan

    @david:

    I’ve heard this before, that there are spambots able to evaluate JavaScript. On this website I’ve had the Hidden Captcha system for a few months and I did not have any spam comments since then. Not one.
    If there will be more spambots with JavaScript support in the future, than Akismet will have to be turned back on and used together with Hidden Captcha. But at least there won’t be as many comments in the Akismet spam list that I’ll have to manually check for false positives.

    The number of people without JavaScript is very small, but still I’m not denying them the right to comment. They just have to fill in the captcha.
    It’s a very small compromise I’m making.

    Anyone please correct me if you think I’m wrong, but I am not taking into account people that have to use screen readers AND don’t have JavaScript support. Because I’m convinced there are no such cases: lack of JavaScript AND the need for a screen reader for the same visitor seems to far fetched.

    If a bot can’t execute javascript why
    not remove the captcha input field?
    There is no need to give check the
    right value if you add the right value
    via javascript, is there? Just check
    if the field is present in the posted
    data or not.

    Not sure if I’m getting this right, but if you mean using JavaScript to remove the captcha input field and then checking its presence on the server, then this wouldn’t allow people without JavaScript to comment, would it?

    ReplyReply
  8. Gravatar Icon Ryan Cullen

    The best anti spam and email hiding solutions are the ones you create yourself as bot authors can’t be bothered to break them. Only when they go big time is it worth the effort.

    ReplyReply
  9. » Using captcha without displaying it — VileWorks, :

    [...] Update: I wrote/recorded a follow up post/screencast explaining how to implement the hidden captcha. [...]

Leave a Reply


info VileWorks uses Gravatars to display the avatars. Get yours at gravatar.com.