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.