django-axes
django-axes copied to clipboard
AXES_USE_USER_AGENT not functioning correctly
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 128d01158cf5de5208dc7edbd5ecab54e0cd8f7c 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.