Skip to main content

Asymmetric Denial of Service

Need

Prevent single requests from overwhelming the application by using excessive resources, thus causing denial of service.

Context

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

Description

Non compliant code

defmodule VulnerableController do
use Plug.Router

plug :match
plug :dispatch

post "/intensive_task" do
# Some resource-intensive task here
intensive_data_processing(conn.params["data"])
send_resp(conn, 200, "Task completed")
end
end

The endpoint '/intensive_task' performs intensive data processing which can consume significant system resources. An attacker can exploit this by making repeated or specially crafted requests, causing the system to become overwhelmed and potentially resulting in denial of service.

Steps

  • 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.
  • Implement a timeout for intensive data processing task to prevent operations from consuming resources indefinitely.
  • Handle potential errors or exceptions during the data processing to prevent crashes.

Compliant code

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 "/intensive_task" do
with {:ok, _result} <- Task.await(intensive_data_processing(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 resource-intensive task. These changes help ensure that no single request or user 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