Skip to main content

Insecure File Upload

Need

Prevent upload of files with double extensions or unsafe extensions

Context

  • Usage of Elixir (v1.10+) for building scalable and fault-tolerant applications
  • Usage of Plug.Upload for file handling

Description

Non compliant code

def upload_file(conn, %{"file" => %Plug.Upload{} = upload}) do
{:ok, file_path} = File.cp(upload.path, "/uploads/#{upload.filename}")
send_resp(conn, 200, "File Uploaded Successfully")
end

The code above is vulnerable as it accepts any uploaded file without validating its extension or content. This can allow an attacker to upload a file with a double extension or an unsafe extension like .html, .php, .exe, or files containing malicious code.

Steps

  • Add a validation function to check the file's extension and ensure it's in a list of safe extensions.
  • Use an antivirus software API to scan the uploaded file for malicious content before saving it to the server.
  • Ensure the 'Content-Type' of the file matches the file's extension.

Compliant code

def upload_file(conn, %{"file" => %Plug.Upload{} = upload}) do
allowed_extensions = ~w(.jpg .jpeg .png)
file_extension = Path.extname(upload.filename)
if file_extension in allowed_extensions and antivirus_scan(upload.path) do
{:ok, file_path} = File.cp(upload.path, "/uploads/#{upload.filename}")
send_resp(conn, 200, "File Uploaded Successfully")
else
send_resp(conn, 400, "Invalid File")
end
end

defp antivirus_scan(file_path) do
# Call antivirus API
end

The secure code validates the uploaded file's extension and ensures it's in a list of allowed extensions. It also scans the file for any malicious content using an antivirus software API. This effectively mitigates the risk of uploading files with double extensions, unsafe extensions, or files containing malicious code.

References