mirror of
https://github.com/zulip/zulip.git
synced 2025-11-16 11:52:01 +00:00
registration: Check realm against PreregistrationUser realm.
We would allow a user with a valid invitation for one realm to use it on a different realm instead. On a server with multiple realms, an authorized user of one realm could use this (by sending invites to other email addresses they control) to create accounts on other realms. (CVE-2017-0910) With this commit, when sending an invitation, we record the inviting user's realm on the PreregistrationUser row; and when registering a user, we check that the PregistrationUser realm matches the realm the user is trying to register on. This resolves CVE-2017-0910 for newly-sent invitations; the next commit completes the fix. [greg: rewrote commit message]
This commit is contained in:
@@ -4000,7 +4000,8 @@ def do_invite_users(user_profile, invitee_emails, streams, invite_as_admin=False
|
||||
for email in validated_emails:
|
||||
# The logged in user is the referrer.
|
||||
prereg_user = PreregistrationUser(email=email, referred_by=user_profile,
|
||||
invited_as_admin=invite_as_admin)
|
||||
invited_as_admin=invite_as_admin,
|
||||
realm=user_profile.realm)
|
||||
|
||||
prereg_user.save()
|
||||
stream_ids = [stream.id for stream in streams]
|
||||
|
||||
@@ -353,7 +353,7 @@ class LoginTest(ZulipTestCase):
|
||||
with queries_captured() as queries:
|
||||
self.register(self.nonreg_email('test'), "test")
|
||||
# Ensure the number of queries we make is not O(streams)
|
||||
self.assert_length(queries, 65)
|
||||
self.assert_length(queries, 67)
|
||||
user_profile = self.nonreg_user('test')
|
||||
self.assertEqual(get_session_dict_user(self.client.session), user_profile.id)
|
||||
self.assertFalse(user_profile.enable_stream_desktop_notifications)
|
||||
@@ -1691,6 +1691,22 @@ class UserSignUpTest(ZulipTestCase):
|
||||
mock_error.assert_called_once()
|
||||
self.assertEqual(result.status_code, 302)
|
||||
|
||||
def test_replace_subdomain_in_confirmation_link(self) -> None:
|
||||
"""
|
||||
Check that manually changing the subdomain in a registration
|
||||
confirmation link doesn't allow you to register to a different realm.
|
||||
"""
|
||||
email = "newuser@zulip.com"
|
||||
self.client_post('/accounts/home/', {'email': email})
|
||||
result = self.client_post(
|
||||
'/accounts/register/',
|
||||
{'password': "password",
|
||||
'key': find_key_by_email(email),
|
||||
'terms': True,
|
||||
'full_name': "New User",
|
||||
'from_confirmation': '1'}, subdomain="zephyr")
|
||||
self.assert_in_success_response(["We couldn't find your confirmation link"], result)
|
||||
|
||||
def test_failed_signup_due_to_restricted_domain(self) -> None:
|
||||
realm = get_realm('zulip')
|
||||
realm.invite_required = False
|
||||
|
||||
@@ -48,9 +48,13 @@ import ujson
|
||||
def create_preregistration_user(email, request, realm_creation=False,
|
||||
password_required=True):
|
||||
# type: (Text, HttpRequest, bool, bool) -> HttpResponse
|
||||
realm = None
|
||||
if not realm_creation:
|
||||
realm = get_realm(get_subdomain(request))
|
||||
return PreregistrationUser.objects.create(email=email,
|
||||
realm_creation=realm_creation,
|
||||
password_required=password_required)
|
||||
password_required=password_required,
|
||||
realm=realm)
|
||||
|
||||
def maybe_send_to_registration(request, email, full_name='', password_required=True):
|
||||
# type: (HttpRequest, Text, Text, bool) -> HttpResponse
|
||||
@@ -74,7 +78,7 @@ def maybe_send_to_registration(request, email, full_name='', password_required=T
|
||||
prereg_user = None
|
||||
if settings.ONLY_SSO:
|
||||
try:
|
||||
prereg_user = PreregistrationUser.objects.filter(email__iexact=email).latest("invited_at")
|
||||
prereg_user = PreregistrationUser.objects.filter(email__iexact=email, realm=realm).latest("invited_at")
|
||||
except PreregistrationUser.DoesNotExist:
|
||||
prereg_user = create_preregistration_user(email, request,
|
||||
password_required=password_required)
|
||||
|
||||
@@ -59,15 +59,13 @@ def accounts_register(request):
|
||||
is_realm_admin = prereg_user.invited_as_admin or realm_creation
|
||||
|
||||
validators.validate_email(email)
|
||||
if prereg_user.referred_by:
|
||||
# If someone invited you, you are joining their realm regardless
|
||||
# of your e-mail address.
|
||||
realm = prereg_user.referred_by.realm
|
||||
elif realm_creation:
|
||||
if realm_creation:
|
||||
# For creating a new realm, there is no existing realm or domain
|
||||
realm = None
|
||||
else:
|
||||
realm = get_realm(get_subdomain(request))
|
||||
if prereg_user.realm is not None and prereg_user.realm != realm:
|
||||
return render(request, 'confirmation/link_does_not_exist.html')
|
||||
|
||||
if realm and not email_allowed_for_realm(email, realm):
|
||||
return render(request, "zerver/closed_realm.html",
|
||||
|
||||
Reference in New Issue
Block a user