If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

In a model add:

ip = request.env.remote_addr
MAX_LOGIN_FAILURES = 3
num_login_attempts = memcache.get(ip) or 0
if num_login_attempts >= MAX_LOGIN_FAILURES:
    auth.settings.login_captcha = Recaptcha(request, ...)


def login_attempt(form):
    memcache.set(ip, num_login_attempts + 1)
auth.settings.login_onvalidation.append(login_attempt)

def login_success(form):
    memcache.set(ip, 0)
auth.settings.login_onaccept.append(login_success)

Related slices

Comments (3)

  • Login to post



  • 0
    villas 13 years ago
    I have also tried this variation. I hope using cache.ram is a reasonable idea.
    ### captcha after failed login attempts
    ip = request.env.remote_addr
    num_login_attempts = cache.ram(ip, lambda: 0) or 0
    if num_login_attempts >= 3:
        #api key is for locahost - if not working, get your own
        auth.settings.login_captcha = Recaptcha(request,\
            '6LedxsASAAAAAAqffUEhN_sJ8GYHexLnF4JE3oWn',\
            '6LedxsASAAAAANjQXMAEinriIZCWuvJk-c3Rq-a2' )
    
    def login_attempt(form):
        cache.ram.increment(ip)
        
    auth.settings.login_onvalidation.append(login_attempt)
    
    def login_success(form):
        cache.ram.clear(ip)
    
    auth.settings.login_onaccept.append(login_success)
    ### ends captcha
    
    Regards, David

  • 0
    richard 13 years ago
    good point - I have changed to IP based. What do you think?

  • 0
    fabianoengler 13 years ago
    ATTENTION users: this CAPTCHA implementation is FLAWED, be careful! Sorry to start this comment this way, but this is important, as it involves security and people may use this slice and have the false notion that it is safe. Ok, now I will explain and support what I am saying (sorry again). CAPTCHA means Completely Automated Public Turing test to tell Computers and Humans Apart. The main reason for a system to tell computers apart from humans is that computer can generate automated input very fast. A common use for this is brute-force attacks and denial of service attacks. The whole idea to use CAPTCHA is exactly to neutralize these kind of attacks, and this is exactly where your slice fails, your proposed implementation of CAPTCHA does not prevent automated input! The flaw here is that you trust on the session to count the login failures. The session implementation in web2py seems to me as secure as it could be, it is not its fault. The problem to use sessions for this kind of stuff is how sessions in general work in the internet: - Client (a browser usually) sends a HTTP request to the system without session information. - The system sees that there is no session information and assumes that it is a new client, then it creates a new session for this client and assign a new session id for it and sends this new session id back to the client. This session id is the only information that web2py sends to the client, all other information stored for the session is stored server side, so the client cannot tamper with it. The counter you used is an example of such information, stored server side. - From now on, when this same client connects again, it will send the session id it received from the server, so the server can identify the client and access the session information. At least, this is what browser usually do, and is the expected behavior. You see, to session handling work, the servers (including server side systems, like web2py) rely on the client behavior of sending its session id, but this cannot be trusted, as the client may not send the session id it received before, and pretend it is a new client. Assuming a the exchange of the session id is secured (ex.: not accessible by xss, traveling only in https, etc.) then you can trust that that if a client has a valid session id, it is who it should be. But the opposite is not true, if a client does not present a session id, it is not necessary a new client. For example, an average user can pretend to be a new client just by cleaning its cookies. For an attacker performing a brute-force attack it will surely not include any session id, not only because this should be very basic for almost any attacker trying to do this, but also because attacker using automated requests will hardly be using a browser for that, but a script or any other program. And a script for this is extremely simple and easy to make, just a couple of shell lines in any linux with, say, wget, can do the trick.. Also note that, in a scenario like this, each automate request causes a server to create a new session, each new session take processing power to calculate the new unique session id and memory to store session info. Considering that it is very easy to achieve request rates of hundreds per second, or even thousands, this is also a very efficient way to perform a denial of service attack by depleting server resources. I don't if web2py specifically has any kind of protection against this kind of DoS attack. But even if it has, that doesn't change the fact that any kind of abuse protection the relies on session info the control the whether CAPTCHA will show or not is fundamentally flawed and easily bypassable. Kind regards, Fabiano.

Hosting graciously provided by:
Python Anywhere