Phx_gen_auth timing based attacks

An excerpt from user.ex:

	@doc """
	Verifies the password.

	If there is no user or the user doesn't have a password, we call
	`Bcrypt.no_user_verify/0` to avoid timing attacks.
	"""

but then user_reset_password_controller.ex defines action function:

  def create(conn, %{"user" => %{"email" => email}}) do
    if user = Accounts.get_user_by_email(email) do
      Accounts.deliver_user_reset_password_instructions(user, &Routes.user_reset_password_url(conn, :edit, &1))
    end

    # Regardless of the outcome, show an impartial success/error message.
    conn
    |> put_flash(:info, gettext("As long as your email is registered in our system, you should soon receive instructions on how to reset your password."))
    |> redirect(to: "/")
  end

where it doesn’t seem to care about the timing differences at all. Is this conscious and correct?

It doesn’t seem like there is any password verification in that controller action. If the reset email is delivered async, then there won’t be any noticeable difference in timing.

+ You can usually find an easier method to check whether a user exists in the system or not, without timing password reset requests.

There’s also the point that phx.gen.auth cannot know how long deliver_user_reset_password_instructions takes. The integrated mailer support was only recently added as well. Previously the default impl used logger messages.

Though I guess it would be nice to add an else clause with a comment that this clause might become problematic.

1 Like

I am personally also not so much convinced that attacks like the ones in question are in fact highly viable ones, especially over the internet. And there may be more effective methods as you mention. But taking the stance that we should protect against them - this here seems like an omission. Taking the stance that this isn’t something worth protecting against, we could drop it from the login handling too. Anyway - I am not advocating either way. If it’s just because in ‘user.ex’ it is pretty easy to mimic the verification (although DB timing might still remain a differentiating factor) and here it’s not then that’s how it is :wink: FWIW I typically put rate limit and IP blacklisting on actions/pages accessible w/o authentication.

That’s available only in the upcoming full Phoenix release, right? As the standalone one I have still logs messages only