Open GoogleCodeExporter opened 9 years ago
This seems to make perfect sense, I'll give it a try when I find a moment.
Original comment by mbonetti
on 12 Dec 2009 at 9:56
On hindsight this is harder than expected, but I'm not giving up :D
Original comment by mbonetti
on 23 Jan 2010 at 11:33
Interesting, what's making it harder? Just curious.
Original comment by eallik
on 23 Jan 2010 at 11:43
Well, one challenge is to find a crypto function that is bundled with Python
2.4+ (as we
don't want to add a dependency on e.g. pycrypto) or come up with a python
implementation of a two-way crypto function I could ship with the app.
I'm open to suggestions, though!
Original comment by mbonetti
on 23 Jan 2010 at 11:51
I'm personally incompetent when it comes to cryptography, but wouldn't a md5
hash with salt suffice? Also,
you could add a SIMPLE_CAPTCHA_CRYPTO setting that would override whatever is
default. Doesn't captcha
usually protect from generic bots anyway? And do generic bots generally have
the ability to break encrypted
form fields? They'd have to know what to look for anyway...
Original comment by eallik
on 23 Jan 2010 at 3:34
I'm afraid MD5 won't do, because we need a way of persisting the challenge &
response between the moment the captcha is instantiated, displayed (a different
view!) and finally validated.
MD5 is a one-way hashing function, i.e. it computes a hash of a given string,
but
there is no way of reversing the hash, so it'd be useless because we'd lose the
challenge and response.
What we need is a full-blown crypto function that computes an encrypted version
of
challenge+response, that can be decrypted back by the image generating and
captcha validating views.
Original comment by mbonetti
on 23 Jan 2010 at 4:34
http://dpaste.com/hold/149454/
Would that suffice?
Original comment by eallik
on 23 Jan 2010 at 5:06
Actually you should consider my last comment void and null :P
Original comment by eallik
on 23 Jan 2010 at 5:23
That isn't completely far off, the only problem is that the scheme is a bit too
easy to
break, and that the alphabet of the input doesn't seem to support unicode.
But I could start from there and maybe convert to and from base64 before
encrypting /
decrypting.
Original comment by mbonetti
on 23 Jan 2010 at 7:01
My (competent) friend recommended to take a look at XTEA/XXTEA, so I went and
found this for Python:
http://code.activestate.com/recipes/496737/
It's in the public domain so you can just grab and use it, and the code itself,
comments stripped, is as short as
mine.
There's also a vanilla RSA implementation that I found. It seems to have no
license so I guess it's basically in the
public domain?
http://code.activestate.com/recipes/572196/
Original comment by eallik
on 24 Jan 2010 at 3:32
XTEA is actually pretty perfect, nice find!
I have a hacked django-simple-captcha implementation running without any models
and it seems pretty solid. I'm gonna run a couple performance tests and will
have to
adapt the unit tests before committing, but it seems pretty good so far.
Original comment by mbonetti
on 24 Jan 2010 at 11:33
I just realized something: if we drop the database persistence we lose the
statefulness of the verification process, which exposes us to a repetition
attack:
* Spammer resolves one captcha, remembers the encrypted key
* Spammer re-posts the same response + key at will
* Captcha verification process always validates because a given
challenge/response
doesn't get "consumed".
Thoughts?
Original comment by mbonetti
on 24 Jan 2010 at 12:44
OK, is it important that you cannot EVER use the same captcha verification
twice? Otherwise you could add a
crypted timestamp and only allow a certain time-window, say, 2 minutes.
And about scraping models -- You could keep them and just implement 2 backends
which the developer can
choose from :)
Original comment by eallik
on 25 Jan 2010 at 4:31
re: 2-minutes time window. This is already implemented and enforced in the
model
backend, but there we also ensure the unicity of the hash to prevent
repeat-attacks.
Problem is, imagine a blog where the only protection against spam is a captcha.
An
attacker could submit 100'000 spam comments in two minutes...
re: two backends. I'd rather not go this way. Going DB-free is tempting: no
need to
syncdb when the developer adds/removes the app, but offering him to chose a
less-
secure solution in exchange of this small improvement is not an option. And
having
to maintain two backends is a bit silly IMO.
I'd rather think of a way of implementing a nonce and add that to the encrypted
part
to make sure the data is only posted once. I'm not sure you can have NONCE's
without a stateful backend, though.
Original comment by mbonetti
on 25 Jan 2010 at 6:33
I have a feeling you are right that a stateful backend is still needed. I will
ask one of my more clever friends,
though. Maybe he has an idea.
Original comment by eallik
on 25 Jan 2010 at 7:17
I think you can get pretty far by using a hash function keyed with the secret
key from settings: (h is an arbitrary hash function, || means concatenation)
* Store h(secret_key || captcha_text) in a hidden field (the user has no way to
get to the captcha_text because he can not invert the hash function.)
* On submission you can check if the submitted value is correct by calculating
the hash again.
Using the secret key prevents the user from just submitting a matching hash of
whatever he entered into the captcha field.
There is no way to prevent repetition attacks but the method above can be
extended to enforce the timeout:
* Store h(secret_key || absolute_time_the_captcha_expires || captcha_text) in a
hidden field and absolute_time_the_captcha_expires in plain in another hidden
field.
* On submission, check if the submitted expiration time and captcha value match
the hash and the time is still in the future.
As above: The user has no way to mess with the hashed data (e.g. change the
expiration time) because he doesn't know the secret key.
Note: If you use a weak hash function, it's possible to obtain the secret key.
I'd recommend some SHA* instead of MD5.
Original comment by da...@dfoerster.de
on 29 Jul 2010 at 1:55
@ #c16
The problem is, what should we use as a timeout? During the validity of the
captcha, say one minute, an attacker can easily submit thousands of valid
forms. Anything under one minute wouldn't be practical (it also depends on the
complexity and length of the form)
I think we do need a nonce to avoid repetition attacks, and the only way to
achieve that seems to be trough persistence.
Original comment by mbonetti
on 29 Jul 2010 at 9:13
Use memory based store, eg. memcache. Or come with your own shared memory store.
Original comment by yuri.pim...@gmail.com
on 25 Dec 2010 at 6:18
Original issue reported on code.google.com by
eallik
on 12 Dec 2009 at 9:32