Problem with TGCaptcha

I am a heavy user of TGCaptcha. I know that Captchas are not the best answer to the spam issue but they limit a lot of problems caused by bots that scan the web for forms.

Last week, I discovered a big flaw in TGCaptcha: it can be bypassed very easily. In this post I will explain how to easily fix the problem, while waiting for the latest version of TGCaptcha.

If a call to a page is made with this URL, everything works fine. The CAPTCHA is verified and an error is reported.
http://127.0.0.1:8080/send?name=dddd&Captcha.captchahidden=3syMBwx_P9VCrN-c7nJeRMe0nVca43Ttf2UrfUvMR0s%3D&Captcha.captchainput=xxx
http://127.0.0.1:8080/send?name=dddd&Captcha.captchahidden=3syMBwx_P9VCrN-c7nJeRMe0nVca43Ttf2UrfUvMR0s%3D&Captcha.captchainput=xxx

However, if you simply remove all the CAPTCHA information from the URL, your form will be validated with no CAPTCHA error.
http://127.0.0.1:8080/send?name=dddd
http://127.0.0.1:8080/send?name=dddd

One way to quickly solve that problem is to test for the CAPTCHA in the method send() and raise an exception when the CAPTCHA information is not present.

Here is an example of the code:
from turbogears import controllers, expose, flash, validate, error_handler 
from turbogears import widgets, validators 
from tgcaptcha import CaptchaField 

class TestForm(widgets.WidgetsList): 
     name = widgets.TextField( 
         validator=validators.NotEmpty(), 
         label="Name:") 
     captcha = CaptchaField( 
         label=' ', 
         help_text=_("Enter the text shown in the image")) 
form = widgets.TableForm(fields=TestForm(), 
                          method="GET", 
                          action="/send", 
                          submit_text=_("Send"),) 

class Root(controllers.RootController):
     @expose(template=".templates.welcome")
     def index(self):
         if tg_exceptions:
             flash(str(tg_exceptions))
         return dict(form=form)

     @expose() 
     @validate(form=form) 
     @error_handler(index)
     @exception_handler(index, "isinstance(tg_exceptions, ValueError)")
     def send(self, **kw):
         if kw.get('Captcha') is None:
             raise ValueError("Captcha Error")
         return kw

from turbogears import controllers, expose, flash, validate, error_handler
from turbogears import widgets, validators
from tgcaptcha import CaptchaField

class TestForm(widgets.WidgetsList):
name = widgets.TextField(
validator=validators.NotEmpty(),
label="Name:")
captcha = CaptchaField(
label=' ',
help_text=_("Enter the text shown in the image"))
form = widgets.TableForm(fields=TestForm(),
method="GET",
action="/send",
submit_text=_("Send"),)

class Root(controllers.RootController):
@expose(template=".templates.welcome")
def index(self):
if tg_exceptions:
flash(str(tg_exceptions))
return dict(form=form)

@expose()
@validate(form=form)
@error_handler(index)
@exception_handler(index, "isinstance(tg_exceptions, ValueError)")
def send(self, **kw):
if kw.get('Captcha') is None:
raise ValueError("Captcha Error")
return kw
 

Leave a message

(Required)
(Required and not displayed)
(Optional)
obfuscated letters Enter the text shown in the image