Stored Cross-Site Scripting (XSS) - Elixir

Stored Cross-Site Scripting (XSS) - Elixir

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