edubadges / audit

Code audit repo for Edubadges
0 stars 0 forks source link

Timing-side channel in API helps testing if an email address is registered #29

Open sveeke opened 6 years ago

sveeke commented 6 years ago

In the badgeuser API BadgeUserForgotPassword() the post() function initiates a password reset procedure. It claims in a comment:

if email_address is None:
    # return 200 here because we don't want to expose information about which emails we know about
    return Response(status=status.HTTP_200_OK)

and later

try:
    user = UserCls.objects.get(pk=email_address.user_id)
except UserCls.DoesNotExist:
    return Response(status=status.HTTP_200_OK)

and then later when everything is alright:

temp_key = default_token_generator.make_token(user)
token = "{uidb36}-{key}".format(uidb36=user_pk_to_url_str(user),
                                key=temp_key)
reset_url = "{}{}?token={}".format(OriginSetting.HTTP, reverse('user_forgot_password'), token)

email_context = {
    "site": get_current_site(request),
    "user": user,
    "password_reset_url": reset_url,
}
get_adapter().send_mail('account/email/password_reset_key', email, email_context)

return Response(status=status.HTTP_200_OK)

The problem is that the early HTTP_200_OK responses create a timing side-channel. Admittedly it is a bit noisy since the target gets a password reset email.