logo

Database

Need

To prevent unauthorized access and control over a user account.

Context

• Usage of Elixir 1.12 for functional programming and building scalable applications

• Usage of Plug for building composable web applications

• Usage of Phoenix web framework for building web applications

Description

1. Non compliant code

defmodule MyAppWeb.PasswordResetController do
  use MyAppWeb, :controller

  def create(conn, %{'email' => email}) do
    user = Accounts.get_user_by_email(email)
    Accounts.deliver_password_reset_instructions(user, conn)
    send_resp(conn, :ok, "")
end...

The code implements a password reset functionality. However, it does not validate whether the requester is indeed the owner of the account. This allows an attacker to request a password reset for any account and receive the reset link, allowing them to takeover that account.

2. Steps

• Implement verification mechanisms to ensure that the person requesting a password reset is indeed the owner of the account.

• This could be done by sending a verification code to the user's registered email before proceeding with the password reset process.

• Ensure that the password reset URL is only sent to the user's registered email and is not exposed anywhere else.

3. Secure code example

defmodule MyAppWeb.PasswordResetController do
  use MyAppWeb, :controller

  def create(conn, %{'email' => email}) do
    user = Accounts.get_user_by_email(email)
    verification_code = Accounts.generate_verification_code(user)
    MyApp.Mailer.deliver_verification_code(user.email, verification_code)
  end...

The code now first sends a verification code to the user's registered email when a password reset is requested. The password reset process only proceeds if the correct verification code is provided, thereby validating that the requester is indeed the owner of the account.

References

417. Account Takeover