auth: Use zxcvbn to ensure password strength on server side.

For a long time, we've been only doing the zxcvbn password strength
checks on the browser, which is helpful, but means users could through
hackery (or a bug in the frontend validation code) manage to set a
too-weak password.  We fix this by running our password strength
validation on the backend as well, using python-zxcvbn.

In theory, a bug in python-zxcvbn could result in it producing a
different opinion than the frontend version; if so, it'd be a pretty
bad bug in the library, and hopefully we'd hear about it from users,
report upstream, and get it fixed that way. Alternatively, we can
switch to shelling out to node like we do for KaTeX.

Fixes #6880.
This commit is contained in:
Mateusz Mandera
2019-11-18 08:11:03 +01:00
committed by Tim Abbott
parent 0c2cc41d2e
commit 06c2161f7e
13 changed files with 175 additions and 19 deletions

View File

@@ -8,7 +8,7 @@ from django.shortcuts import redirect, render
from django.conf import settings
from zerver.decorator import require_realm_admin, require_member_or_admin
from zerver.forms import CreateUserForm
from zerver.forms import CreateUserForm, PASSWORD_TOO_WEAK_ERROR
from zerver.lib.events import get_raw_user_data
from zerver.lib.actions import do_change_avatar_fields, do_change_bot_owner, \
do_change_is_admin, do_change_default_all_public_streams, \
@@ -38,6 +38,7 @@ from zerver.models import UserProfile, Stream, Message, email_allowed_for_realm,
DomainNotAllowedForRealmError, DisposableEmailError, get_user_profile_by_id_in_realm, \
EmailContainsPlusError, get_user_by_id_in_realm_including_cross_realm, Realm, \
InvalidFakeEmailDomain
from zproject.backends import check_password_strength
def deactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
user_id: int) -> HttpResponse:
@@ -450,6 +451,9 @@ def create_user_backend(request: HttpRequest, user_profile: UserProfile,
except UserProfile.DoesNotExist:
pass
if not check_password_strength(password):
return json_error(PASSWORD_TOO_WEAK_ERROR)
do_create_user(email, password, realm, full_name, short_name)
return json_success()