registration: Prevent injecting arbitrary strings via query param.

While the query parameter is properly excaped when inlined into the
template (and thus is not an XSS), it can still produce content which
misleads the user via carefully-crafted query parameter.

Validate that the parameter looks like an email address.

Thanks to jinjo2 for reporting this, via HackerOne.
This commit is contained in:
Alex Vandiver
2023-12-08 14:01:42 +00:00
committed by Tim Abbott
parent 9067220af6
commit bedb68b2fe
2 changed files with 30 additions and 0 deletions

View File

@@ -2935,6 +2935,24 @@ class UserSignUpTest(ZulipTestCase):
form.errors["email"][0], form.errors["email"][0],
) )
def test_signup_confirm_injection(self) -> None:
result = self.client_get("/accounts/send_confirm/?email=bogus@example.com")
self.assert_in_success_response(
[
'check your email account (<span class="user_email semi-bold">bogus@example.com</span>)'
],
result,
)
result = self.client_get(
"/accounts/send_confirm/?email={quote(email)}",
{"email": "bogus@example.com for example"},
)
self.assertEqual(result.status_code, 400)
self.assert_in_response(
"The email address you are trying to sign up with is not valid", result
)
def test_access_signup_page_in_root_domain_without_realm(self) -> None: def test_access_signup_page_in_root_domain_without_realm(self) -> None:
result = self.client_get("/register", subdomain="", follow=True) result = self.client_get("/register", subdomain="", follow=True)
self.assert_in_success_response(["Find your Zulip accounts"], result) self.assert_in_success_response(["Find your Zulip accounts"], result)

View File

@@ -914,6 +914,18 @@ def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> Ht
@has_request_variables @has_request_variables
def signup_send_confirm(request: HttpRequest, email: str = REQ("email")) -> HttpResponse: def signup_send_confirm(request: HttpRequest, email: str = REQ("email")) -> HttpResponse:
try:
# Because we interpolate the email directly into the template
# from the query parameter, do a simple validation that it
# looks a at least a bit like an email address.
validators.validate_email(email)
except ValidationError:
return TemplateResponse(
request,
"zerver/invalid_email.html",
context={"invalid_email": True},
status=400,
)
return TemplateResponse( return TemplateResponse(
request, request,
"zerver/accounts_send_confirm.html", "zerver/accounts_send_confirm.html",