Prevent persistent injection of malicious scripts into application fields
defmodule VulnerableController do
use MyWeb, :controller
def create(conn, %{"message" => message_params}) do
%Message{} |> Message.changeset(message_params) |> Repo.insert()
redirect(conn, to: message_path(conn, :index))
end
def index(conn, _params) do
messages = Repo.all(Message)
render(conn, "index.html", messages: messages)
end
end
This vulnerable code saves user-provided messages directly to the database without sanitizing the input first. Then it uses this data to generate dynamic content on the index page. An attacker can store a malicious script in the message, which will be executed by the user's browser when the index page is loaded.
defmodule SecureController do
use MyWeb, :controller
use Phoenix.HTML
def create(conn, %{"message" => message_params}) do
sanitized_params = %{"content" => h(message_params["content"])}
%Message{} |> Message.changeset(sanitized_params) |> Repo.insert()
redirect(conn, to: message_path(conn, :index))
end
def index(conn, _params) do
messages = Repo.all(Message)
render(conn, "index.html", messages: messages)
end
end
The secure code uses the 'h' function from the Phoenix.HTML package to sanitize user-provided input before saving it to the database. This ensures that any HTML special characters in the input are escaped, preventing them from being interpreted as part of the HTML markup. This mitigates the stored XSS vulnerability by preventing scripts from being stored and later executed in the user's browser.