Hi Tom,
> Hello Everyone,
>
> I noticed that Django's contrib.auth doesn't provide a mechanism
> for detecting a password brute force attack. This is necessary for
> a couple projects I'm working so I have to implement some kind of
> solution and would really like to do it in such a way that it
> could get contributed back to the community. I'd like to propose
> possible two variants to the way that system works and would
> appreciate feedback.
>
> The first option is the more user customizable one, I propose a new
> signal (possibly called LoginAttempt) which User.check_password()
> would fire before returning so that users could implement their own
> logging and lockout policies. This is likely what I will implement
> first so that our internal implementation doesn't interfere with
> future general implementations.
The problem with signals is that they don't return values, and so the
mechanism can't interact with the actual login process. It can only
notice that something is going on and try to stop it by some external
mechanism.
> The second option, which is much more thorough, would add a
> LoginAttemptLogEntry model which would look something like this:
>
> class LoginAttemptLogEntry(models.Model):
> user = models.ForeignKey(User, null=True)
> datetime = models.DateTime(auto_now_add=True)
> success = models.BooleanField()
>
> Then either ModelBackend.authenticate() or User.check_password()
> would log each login attempt using the LoginAttemptLogEntry. Any
> user's account which had more than N (configurable in settings,
> default to 5?) consecutive unsuccessful login attempts would get
> locked. A successful password reset would then re-enable the
> account.
Personally, I really dislike this kind of thing. It makes it trivial
to allow an attacker to lock out a user, just by knowing their
username. The password reset mechanism has two disadvantages:
1) It won't work if the user's e-mail address is out of date.
A user who has not forgotten their password should not be forced
to keep their e-mail address up to date if they don't need it to
be.
2) It's really inconvenient. This kind of security policy pushes the
cost of the attack onto the user, who hasn't done anything wrong.
So I would be against this as a default implementation, or as any
implementation included in Django. (I understand that this is probably
coming from customer requirements).
Simon's rate limiting sounds like a better idea, since it doesn't
require a reset and limits on IP address, so that the user isn't
affected by the attacker's antics.
As for integrating a solution, for either one of these it can already
be done without a new signal, and a solution like Simon's cannot be
done with signals). You simply wrap the view function in question in
some code that implements your policy (possibly using a decorator like
Simon's does). For protecting the admin, this can be done by using an
AdminSite mixin that overrides the 'login' method.
So if you want to contribute your work to the community, I would do it
as an external project. But as other people have mentioned, check out
the existing projects.
Regards,
Luke
--
"I'm at peace with the world. I'm completely serene. I know why I
was put here and why everything exists. I am here so everybody can
do what I want. Once everybody accepts it, they'll be serene too."
(Calvin and Hobbes)
Luke Plant || http://lukeplant.me.uk/
--
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-developers?hl=en.