Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Login form is vulnerable to Password Guessing Attack #442

Open
imscary opened this issue Apr 24, 2019 · 10 comments
Open

Login form is vulnerable to Password Guessing Attack #442

imscary opened this issue Apr 24, 2019 · 10 comments

Comments

@imscary
Copy link
Contributor

imscary commented Apr 24, 2019

The login system will not take a pause or block you for few minutes even if you try 100 incorrect passwords. This can be exploited very easily with Hatch or bruteforcing the form action request password input data with a valid csrf token until the different response. This can be avoided with 5 minutes wait time on every 5 incorrect passwords for a specified acconut. I don't know how to implement that on Django.

@dwitterer
Copy link
Contributor

I assume you'd need some sort of localstorage value that tracks the number of incorrect attempts and then implement some logic around that in the login form. I'll see if I can give it a go when I get home in about 3 hours, but of course you're free to implement this before then if you want to...

@stianjensen
Copy link
Collaborator

If you want this kind of security, I would implement it on the backend in django, and not in the frontend, where it's relatively easy to bypass.

@dwitterer
Copy link
Contributor

Well I mean, that's a good point. Now that I think about it, we could just add an entry to the database with the count of incorrect logins for each user, then use that. Then it'd be entirely backend as well...

I'm not at all good with databases though 😂

@stianjensen
Copy link
Collaborator

Yep a counter could work in that case, and having it reset to zero when you correctly login. But then you would also need a mechanism to have it reset after a bit of time.

Packages like django-defender and django-axes do this for you.

@imscary
Copy link
Contributor Author

imscary commented Apr 24, 2019

Yes but what computer info must we register into the DB? The IP? Using an attack tool with dynamic proxies can change ip for every password in the wordlist.

@dwitterer
Copy link
Contributor

I mean, we store a list of users in the database, so we'd just implement it into that. Like:

User: kipkat
Blah: bleh
Whatever: whatever
Login_attempts: 2

Right? We don't need the IP... Just the number of login attempts for each user on the site.

@imscary
Copy link
Contributor Author

imscary commented Apr 24, 2019

Oh, good point.

@imscary
Copy link
Contributor Author

imscary commented Apr 25, 2019

If I think a little bit, an attacker can spam an incorrect password all the day and that will make the account impossible to access by anyone if it's blocked. (based on that last engine you said)

@joeytwiddle
Copy link
Collaborator

joeytwiddle commented Apr 30, 2019

That's also an important point kipkat. Gotta be careful when throttling that we don't create a denial of service opportunity.

Attackers can change IP often, but I doubt they have the 1,000,000 proxies needed for brute-force.

In my APIs I use this approach:

  • A cooldown mechanism which allows 20 initial guesses for free, but after that max 2 per minute

  • But actually, it's a separate cooldown monitor for each IP address (attacker can only DOS himself)

  • Occasionally, clean up any cooldown monitors which have gone cold (to prevent memory/DB leaks)

  • Optional: Do it all in memory rather than DB (avoids race condition if 30 requests are made in parallel; for multiple API servers could maybe use a redis cache?)

The cooldown mechanism itself works like this:

  • Store the last known temperature, and the last time the temperature was read

  • Max temperature (aka overheat) is 20 degrees

  • Each guess causes +1 degree warming (or is rejected if overheated, with no warming)

  • Cooldown rate is -2/60 degrees per second

  • Apply (interpolate) any uncounted cooling just before reading the temperature (to avoid having to iteratively update temperatures every second)

Here is the cooldown monitor code. But the cache of IP->CooldownMonitor is not there.


Now I read Stian's comment about some existing solutions for django! :)

@rep-movsd
Copy link
Collaborator

I implemented something like this for the web portal for my employer

Basically, you have a login_attempts table which counts logins with latest timestamp for both IP and username, and won't allow more than one in 3 minutes after 5 failed logins. After 10 the account is locked.

There is another option - use fail2ban on the server - it generally blocks all kinds of DDos attempts by scanning web logs and changing the firewall rules.

I use this on my personal websites on digitalocean

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants