mbi / django-simple-captcha

Django Simple Captcha is an extremely simple, yet highly customizable Django application to add captcha images to any Django form.
http://django-simple-captcha.readthedocs.io/en/latest/
MIT License
1.38k stars 322 forks source link

if code is used once, deny it to be reused #220

Closed michaelhjulskov closed 1 year ago

michaelhjulskov commented 1 year ago

Hi

I experience a hacker attempt the hacker succedded guessing a code because (i guess) he reads the captcha code manually and then his script keeps using the same code to attempt guessing the code

So I suggest that: once form is submitted with correct captcha code - ban this code from working for some time

i guess that random code (or challenge) are noted in database and then shown to user then this code will work for xx seconds and thats fine but we also need to limit the number of times the code can be used with success. success limit should be default 1 - but maybbe in some use cases we want it to be more that 1 (i dont know)

Michael

michaelhjulskov commented 1 year ago

or maybe that is exactly what is happening here???? if code exist, its valid, and deleted. ???

https://github.com/mbi/django-simple-captcha/blob/9d94c6dec3d93e5878ef67b3439b43be13a03f76/captcha/fields.py#L266-L275

mbi commented 1 year ago

Yes, that's exactly what is supposed to happen there. By design, once used, a captcha cannot be reused, or it would be trivial to just resubmit a (valid) response to always pass validation.

So I'm not quite sure what happened in your case?

michaelhjulskov commented 1 year ago

I can see the user made more that 800 attempts to guess the code of two orders I dont believe he did that work manually

I added a limit of 20 attempts in my code - after 20 attempts order is locked and he loses his payment

but I am curious how he did it - he is not a advanced developer - i know exactly who did it

michaelhjulskov commented 1 year ago

Please confirm that the captcha code should be deleted in database after one successfull call to if form.is_valid(): .....

correct?

michaelhjulskov commented 1 year ago

Here is my settings by the way

CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge' CAPTCHA_FOREGROUND_COLOR = '#001100' CAPTCHA_TIMEOUT = 360 CAPTCHA_MATH_CHALLENGE_OPERATOR = '*' CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',) CAPTCHA_LETTER_ROTATION = (-22,22) CAPTCHA_2X_IMAGE = True

mbi commented 1 year ago

Well he probably just tried to brute-force the CAPTCHA, but that doesn't mean he actually succeeded, or do you see evidence to the contrary?

michaelhjulskov commented 1 year ago

he actually succeeded submitting the form.is_valid() more than 800 times

so either he found some way to get around the captcha, or he did it manually and now is very tired

i suspect he found a way to cheat the captcha

mbi commented 1 year ago

Well, to an extent, image based captcha (such as django-simple-captcha) are obviously beatable using OCR and/or AI, and sometimes it's just worthwhile to have a human solve CAPTCHAs at scale.

I'm going to close this because I assume either of those things happened (or maybe there is a configuration issue or whatnot) and that the attacker didn't find a generic way to defeat the library. Please feel free to reopen if you have more evidence and/or a POC that django-simple-captcha has an exploitable flaw that can be abused to bypass is_valid().