Insecure Functionality
Need
Prevent unauthorized password change
Context
- Usage of Elixir (1.10 and above) for building scalable and fault-tolerant applications
- Usage of Phoenix Framework for building scalable web applications
Description
Non compliant code
def change_password(conn, %{'security_code' => _security_code, 'new_password' => new_password}) do
user = conn.assigns.current_user
user = User.changeset(user, %{password: new_password})
Repo.update!(user)
send_resp(conn, :ok, 'Password updated')
end
In the insecure code example, the server changes the user's password without verifying the security code provided by the user. This allows an attacker to change a user's password without the correct security code.
Steps
- Always validate the security code on the server-side before changing the password.
- Ensure that the security code expires after a certain time period to limit the time window for an attack.
- Lock the account or require additional verification if there are too many failed attempts to enter the security code.
Compliant code
def change_password(conn, %{'security_code' => security_code, 'new_password' => new_password}) do
user = conn.assigns.current_user
if check_security_code(user, security_code) do
user = User.changeset(user, %{password: new_password})
Repo.update!(user)
send_resp(conn, :ok, 'Password updated')
else
send_resp(conn, :unauthorized, 'Incorrect security code')
end
end
In the secure code example, the server first checks if the provided security code matches the one stored in the database for that user. If it does not, the server returns an 'Unauthorized' response. This ensures that an attacker can't change a user's password without the correct security code.