How to do it?Designing CAPTCHA challenge is hard - you need to fight OCRs (if the CAPTCHA is based on image recognition) and cheap labour (attackers pay $12 for solving 500 CAPTCHA, according to OWASP). On the other hand, it needs to be solvable by your users - so this one, while certainly being a strong challenge, is probably not a good idea ;)
But no matter what the challenge, the whole CAPTCHA architecture must be secure. For example:
- it must be protected against replay attacks (CAPTCHA ID generated once cannot be reused)
- CAPTCHA given for one session should not be valid in other session. There must be a relation between CAPTCHA and a session, so that the attacker won't solve the CAPTCHA (e.g. manually) in his own session and submit the solved value in the other session.
- CAPTCHA solution must not be stored on the client
- it must be protected against brute-force attack (e.g.require another CAPTCHA after a few invalid responses)
- The amount of possible CAPTCHAs must be A Big Number (bruteforce protection).
I really recommend all the developers to read Strong CAPTCHA guidelines as many design issues are tricky.
MotionCAPTCHA - The fail of the dayWhat pushed me into writing this blog post is the MotionCAPTCHA project I encountered. It's a HTML5 (yay!) canvas based project where the challenge is to repeat drawing a given shape to prove being a human. I've seen a few broken CAPTCHAs in my life, but this one is just over the top. Just two examples:
These are the available shapes (all 16 of them):
And this is how you implement it (cited from the readme):
- You manually disable your form, by emptying the form's
actionattribute, and placing its value in a hidden
<input>with a specific ID. You should also put
disabled="disabled"on the submit button, for added points.
- You add a few HTML lines to your form to initialise the MotionCAPTCHA canvas, and add the plugin's scripts to your page.
- The user draws the shape and, if it checks out, the plugin inserts the form's
<form>tag. The user can submit the form, happy days.
I mean, WTF? So the form looks like this: