Lack of data validation - Path Traversal
Need
Restriction of downloadable files to a fixed directory
Context
• Usage of Elixir 1.16+ for building application services
• Usage of Plug.Router for handling HTTP requests
Description
1. Non compliant code
defmodule MyAppWeb.ReportsRouter do
use Plug.Router
plug :match
plug :fetch_query_params
plug :dispatch
get "/download" do...The `/download` route below appends the `file` query parameter to `"priv/reports/"` and sends the result with `send_file/3`. The caller controls the path. A request to `/download?file=../../config/runtime.exs` climbs out of the reports directory with `..` segments and downloads the configuration of the application, and similar values reach `/etc/passwd`, private keys or the release files. `File.read/1` and `File.stream!/1` called with request data have the same problem.
2. Steps
• Never pass request data directly to `send_file/3`, `File.read/1`, `File.stream!/1` or `Path.expand/1`.
• Resolve user-supplied names with `Path.safe_relative/2` against a fixed base directory and reject `:error`.
• Confirm with `File.regular?/1` that the resolved path is a regular file before sending it.
• Prefer looking files up by an identifier stored in the database instead of by a path sent by the client.
• Run the application with a filesystem user that can only read the directories it serves.
3. Secure code example
defmodule MyAppWeb.ReportsRouter do
use Plug.Router
@reports_dir "priv/reports"
plug :match
plug :fetch_query_params
plug :dispatch...The corrected route resolves the parameter with `Path.safe_relative/2` before touching the filesystem. `Path.safe_relative/2` returns `:error` for absolute paths, for any path that uses `..` to leave the base directory and for symbolic links inside the base directory that point outside it. Only when it returns `{:ok, relative}` is the value joined to the reports directory. `File.regular?/1` then confirms that the target is a regular file, so directories and special files are never sent. Anything that fails these checks receives `404 Not Found`, which does not reveal whether the file exists.
References
• 063. Lack of data validation - Path Traversal