Skip to main content

External Control of File Name or Path

Need

To prevent unauthorized access and alteration of system files

Context

  • Usage of Elixir for building scalable and fault-tolerant applications
  • Usage of Elixir Phoenix Plug for building web applications
  • Usage of file-upload handling for untrusted sources

Description

Non compliant code

defmodule VulnerableApp.FileUploadController do
use VulnerableApp.Web, :controller

def upload(conn, %{"file" => file, "filename" => filename}) do
File.write(filename, file)
send_resp(conn, 200, "File uploaded successfully")
end
end

The following Elixir code receives an uploaded file and its filename from an untrusted source and directly uses the given filename to save the file. This leaves the application open to manipulation from an attacker.

Steps

  • Use a library such as plug to handle file uploads securely.
  • Do not use the original filename from the user. Generate a new filename on the server side.
  • Restrict the storage of uploaded files to a specific directory.

Compliant code

defmodule SecureApp.FileUploadController do
use SecureApp.Web, :controller

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

defp generate_filename() do
:crypto.strong_rand_bytes(20) |> Base.url_encode64()
end
end

The following Elixir code receives an uploaded file from an untrusted source, generates a new filename and saves the file to a specified directory. This prevents an attacker from manipulating the file name or path.

References