Skip to main content

Insecure file upload - Files Limit

Need

To prevent system resources exhaustion by limiting the number of files uploaded and replacing old files with new ones.

Context

  • Usage of Elixir (1.12.0 and above) for building scalable and fault-tolerant applications
  • Usage of Phoenix Framework for building web applications
  • Usage of Plug.Upload for handling file uploads in Elixir

Description

Non compliant code

defmodule MyAppWeb.UploadController do
use MyAppWeb, :controller

def upload(conn, %{"file" => file}) do
{:ok, _} = File.write("./uploads/" <> file.filename, file.read)
send_resp(conn, 200, "File uploaded")
end
end

In this insecure code example, a new file is written to the server's storage every time the upload endpoint is hit. There is no limit to the number of files that can be uploaded, and old files are not replaced with new ones. This could potentially lead to resource exhaustion on the server.

Steps

  • Modify the upload function to delete old files before writing new ones.
  • Apply request throttling to limit the rate at which files can be uploaded.

Compliant code

defmodule MyAppWeb.UploadController do
use MyAppWeb, :controller

def upload(conn, %{"file" => file}) do
dir = "./uploads/"
old_files = File.ls!(dir)
Enum.each(old_files, &File.rm(dir <> &1))
{:ok, _} = File.write(dir <> file.filename, file.read)
send_resp(conn, 200, "File uploaded")
end

defp limit_rate(conn, _opts) do
:timer.sleep(1000)
conn
end

plug :limit_rate when action in [:upload]
end

In this secure code example, the server deletes old files before writing new ones. Additionally, a plug function limits the rate at which files can be uploaded, thus preventing resource exhaustion on the server.

References