logo

Symmetric Denial of Service - Elixir


Need

Prevent a sequence of repeated requests from consuming excessive resources, leading to denial of service.


Context

  1. Usage of Elixir 1.13.0 for building scalable and fault-tolerant applications
  2. Usage of Plug and Cowboy for request management
  3. Usage of a library for handling extensive data processing or resource-intensive tasks

Description

Insecure Code Example

defmodule VulnerableController do
  use Plug.Router

  plug :match
  plug :dispatch

  post "/long_running_task" do
    # Long running task here
    intensive_data_processing(conn.params["data"])
    send_resp(conn, 200, "Task completed")
  end
end

The endpoint '/long_running_task' executes a long running task which can consume significant system resources. An attacker can exploit this by making repeated requests, causing the system to become overwhelmed and potentially leading to denial of service.

Steps

  1. Implement rate limiting using the plug_attack package to limit the number of requests a single client can make in a given period of time.
  2. Implement a timeout for long running tasks to prevent operations from consuming resources indefinitely.
  3. Handle potential errors or exceptions during the data processing to prevent crashes.

Secure Code Example

defmodule SecureController do
  use Plug.Router
  use PlugAttack

  plug :match
  plug :dispatch
  plug PlugAttack.Blocker, otp_app: :my_app

  plug PlugAttack.RateLimiter,
    name: "api/ip",
    interval: 60_000,
    allow: 100

  post "/long_running_task" do
    with {:ok, _result} <- Task.await(long_running_task(conn.params["data"]), 5000) do
      send_resp(conn, 200, "Task completed")
    else
      _ -> send_resp(conn, 503, "Server is busy. Please try again later.")
    end
  end
end

This solution implements rate limiting using the plug_attack package and adds a timeout to the long running task. These changes help ensure that no sequence of repeated requests can consume too many resources, thus mitigating the denial of service risk. If the task doesn't finish within the specified time, a 'Server is busy. Please try again later.' message is sent to the client.


References

  • 003 - Symmetric Denial of Service

  • Last updated

    2023/09/18