Skip to main content

Server-side Request Forgery (SSRF)

Need

To prevent unauthorized network requests performed by the server due to user input manipulation

Context

  • Usage of Elixir (v1.11+) for building scalable and fault-tolerant applications
  • Usage of Plug.Adapters.Cowboy2.Http module for handling HTTP requests in Elixir
  • Usage of httpc module for making HTTP requests

Description

Non compliant code

defmodule MyAppWeb.PageController do
use MyAppWeb, :controller

def external_request(conn, %{"url" => url} = _params) do
{:ok, response} = :httpc.request(url)
text(response)
end
end

In this insecure code, the Elixir/Phoenix application accepts a URL from user input and makes a HTTP request to it using the :httpc.request function. This is a server-side request forgery (SSRF) vulnerability, as a malicious user could manipulate the input to make the server perform unauthorized requests.

Steps

  • Don't allow user input to dictate the server's network requests directly.
  • If user input must be used to make network requests, implement strict input validation and only allow requests to approved domains.
  • Consider using a safe-list of approved domains that the server can make requests to.

Compliant code

defmodule MyAppWeb.PageController do
use MyAppWeb, :controller

def external_request(conn, %{"url" => url} = _params) do
if validate_url(url) do
{:ok, response} = :httpc.request(url)
text(response)
else
send_resp(conn, 400, "Invalid URL")
end
end

defp validate_url(url), do: Enum.member?(["http://approved1.com", "http://approved2.com"], url)
end

In this secure code, the application still accepts a URL from user input. However, it now validates the input with a validate_url function, which checks if the input is part of a list of approved domains. This mitigates the SSRF vulnerability by preventing the server from making requests to unapproved domains.

References