jazzband / django-axes

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

BUG: AXES_PASSWORD_FORM_FIELD fails to redact password field from AccessAttempt.post_data if a custom login form prefix is used.

michaeljtbrooks opened this issue · comments

Describe the bug
If a custom login form implementation in Django uses a form prefix and a custom password field name, then AXES_PASSWORD_FORM_FIELD will fail to redact that field from the request.POST and request.GET if AXES_PASSWORD_FORM_FIELD is set to just the form's password fieldname without the prefix as the variable's name implies.

The documentation implies that no prefix is necessary: "The name of the form or credentials field that contains your users password."

Confusingly settings.AXES_USERNAME_FORM_FIELD works fine without the prefix because when it is pulled from credentials (see axes.helpers.get_client_username), this would be the form's username field name without the form's prefix. There is then the fallback method to pull from request.POST which would need the prefix.

Thus, if a developer uses a custom login form with a form prefix, and sets AXES_USERNAME_FORM_FIELD to the field name without the prefix, things will work fine and the username will be found. But if they also set AXES_PASSWORD_FORM_FIELD to the form's password field name without the form prefix, then Axes will fail to redact the password.

To Reproduce
Steps to reproduce the behavior:

  1. Create a custom login form view, where the authentication form has a username field called "uname" and a password field called "pword" and is initialised with a prefix e.g. "login"
  2. Set settings.AXES_USERNAME_FORM_FIELD to "uname"
  3. Set settings.AXES_PASSWORD_FORM_FIELD to "pword"
  4. Attempt to login, deliberately getting the login credentials wrong
  5. Inspect the database, check the last entry for AccessAttempt, you'll see "login-pword" appear in the post_data

Expected behavior
The request.POST and request.GET cleansing routine (AxesDatabaseHandler.user_login_failed -> get_query_str() -> cleanse_parameters()) should be able to strip keys matching (?:.*-)?{AXES_PASSWORD_FORM_FIELD} from the querydict.

We won't know the form prefix at the level of inspecting the request.POST querydict, thus it'll have to be a wildcard match. If you want to be more specific, you could introduce a new setting: AXES_LOGIN_FORM_PREFIX, defaulting to "", and thus strip keys with and without this prefix.

A less robust fix would be to update the documentation to explain that any custom form prefix is necessary for AXES_PASSWORD_FORM_FIELD, but that would be a bit lame IMO.

Your environment
python version: 3.9
django version: 3.2
django-axes version: 6.1.1
Operating system: Linux Mint 21.2

Thanks for reporting. Would someone like to open a PR for the fix?