Skip to main content

Insecure functionality - Fingerprint

Need

Ensure that only authorized fields can be updated by the user

Context

  • Usage of Elixir (v1.12+) for building scalable and fault-tolerant applications
  • Usage of Ecto for data persistence

Description

Non compliant code

defmodule UserController do
def update(conn, %{'user' => user_params, 'id' => id}) do
user = Repo.get(User, id)
changeset = User.changeset(user, user_params)
Repo.update(changeset)
end
end

The code below is insecure because it allows any field of the user to be updated without checking if the field is allowed to be updated. This could lead to unauthorized updates to fields that should be read-only after account creation, like 'email', or worse, 'admin' status.

Steps

  • Define a whitelist of fields that can be updated.
  • Use the Ecto.Changeset.cast/4 function to only allow updates to the whitelisted fields.

Compliant code

defmodule UserController do
def update(conn, %{'user' => user_params, 'id' => id}) do
user = Repo.get(User, id)
changeset = User.changeset(user, user_params, ~w(username age)a)
Repo.update(changeset)
end
end

The code below is secure because it only allows 'username' and 'age' to be updated. The 'admin' and 'email' fields are not included in the whitelist, so they cannot be updated even if they are included in the user_params map.

References