Once bug 587896 is closed we'll be tracking last log in, # of attempts, and IPs. That should be enough to figure out some kind of rate-limiting algorithm for user log ins. The `locked` timestamp in the db should be set when an account is locked.
mcoates - maybe you have an algorithm for this already?
Yes I do. I'm floating this within our team for feedback and will then post it here.
Sorry for the delay, we'll have a response on Wednesday.
There are lots of ways of approaching this issue. In this situation (public facing web app) we recommend the following two-pronged approach. This will defend against a targeted brute force attack against a specific account and also defend against an attacker trying one or two common passwords against hundreds of user accounts. The accounts are never actually locked, instead a CAPTCHA is selectively used to prevent automated brute force attacks. - The rate-limiting mechanism is a CAPTCHA prompt. - Accounts are never actually "locked" - The CAPTCHA is presented in the following two scenarios: 1. Greater than X failed logins for a particular user account from any number of IP addresses. 2. Greater than Y failed logins from a particular IP address against any number of user accounts. - In each scenario the CAPTCHA must be correctly completed before any more login attempts will be processed for the target username (scenario 1) or from the source IP address for any target username (scenario 2) - The failed login counter for a user is cleared upon a successful authentication to that username (scenario 1) - The failed login counter for an IP address is cleared after Z minutes of the last failed login from the IP. During the Z minutes login requests are not processed from the malicious IP address. - Successfully answering the CAPTCHA also clears the failed login counter in both scenarios. Let's setup X,Y,Z as configurable thresholds that we can easily adjust as needed. I recommend the following initial settings: X: 5 Y: 15 Z: 10 minutes
Sounds like incrementing memcached keys would be good here.
Lets use django-ratelimit for this.