Skip to main content

Stored Cross-Site Scripting (XSS)

Need

Prevent persistent injection of malicious scripts into application fields

Context

  • Usage of Elixir 1.13.0 for building scalable and fault-tolerant applications
  • Usage of Ecto for database query and manipulation
  • Usage of Phoenix.HTML for building HTML
  • Usage of application state management for dynamic content generation

Description

Non compliant code

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.

Steps

  • Use the functions provided by the Phoenix.HTML package to sanitize user input before storing it in the database.
  • Replace raw database data with the 'h' function from Phoenix.HTML when generating dynamic content.

Compliant code

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.

References