Insecure file upload - Files Limit - Elixir

Insecure file upload - Files Limit - Elixir

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