jazzband / django-axes

Keep track of failed login attempts in Django-powered sites.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AXES_USE_USER_AGENT not functioning correctly

cjtapper opened this issue · comments

This might be a duplicate of #677, but the user there did not provide enough detail for me to be sure.

I am using the following versions of Django and Axes:

django==3.2.16
django-ipware==4.0.2
django-axes==5.39.0

My Axes configuration is as follows:

AXES_FAILURE_LIMIT = 5
AXES_COOLOFF_TIME = dt.timedelta(hours=1)
AXES_HANDLER = "axes.handlers.cache.AxesCacheHandler"
AXES_USERNAME_FORM_FIELD = "email"
AXES_USE_USER_AGENT = True

When I reach the 5 failure limit with a given (ip, user_agent) pair, I am locked out. If I change to a different user agent, I am still locked out. This is not expected, and the docs do not reflect this behaviour either. If I have AXES_USE_USER_AGENT = True, I would expect that using the same IP but a different user agent would reset the count.

It also appears that if, for example, I had 5 attempts with (ip_1, user_agent_1), and then tried to log in with a different ip address (let's call it ip_2) but the same user agent string, I am also blocked out. It appears to lock out via user agent string, even if the IP is different!

Happy to provide more detail if necessary. I can also start digging into the code and/or provide some tests that prove these bugs exist, just haven't had the time yet...

I can confirm that this does not appear to be a problem with AxesCacheHandler specifically - I have tested with AxesDatabaseHandler as well, and I am seeing the same bug.

This was bug was introduced in commit 128d011 in the get_client_parameters function. The user_agent should be being set in the same dict as the ip_address, rather than appending a new dict with user agent onto the filter_query list

There is not sufficient test coverage around the AXES_USE_USER_AGENT feature - this is a fairly major regression!

Thank you for the detailed report @cjtapper. Would you or @PetrDlouhy be interested in issuing a fix for this?

Happy to give feedback / review on any PRs that are opened related to this, but unfortunately I don't have the time to work on the fix myself

I will look into it today or tomorrow.

BTW By coincidence our service was today subject of brute force attack probably by a leaked e-mail - password list. The attacker did probably broke into 3 free (insignificant) accounts.
I realized, that I didn't have the option AXES_LOCK_OUT_BY_USER_OR_IP on.
From this experience I would recommend to have it always on.

I made a fix in #950, please test.

Note: the utils.reset_requests() function doesn't work with AXES_USE_USER_AGENT=True. That function was never implemented.

LGTM. Should the reset_requests utility have added documentation and/or raise a warning if it is being used with user agent support enabled?

@aleksihakli I don't know. If the behavior is dangerous I would suggest even raising NotImplementedError exception.

But maybe the default behavior is not that bad. It would probably re-enable more access possibilities than needed on the reset, but it could still be safe enough.