Skip to main content

Insecure File Management

Why is this important?

Any functionality related to file management requires careful usage. If attackers are able to influence the input to file access related APIs, then it can have a serious impact. For example, attackers could read all files on your application server.

In other cases, this can allow attackers to include their own code, or files, that are then executed by the application at runtime.

Check out this video for a high-level explanation on local file inclusion issues:

Local File Inclusion

Another high-level explanation on remote file inclusion issues:

Remote File Inclusion

Fixing Insecure File Management

Option A: Sanitize the Filename

The filename provided by the send_download API can be tampered with by the client to reference unauthorized files.

For example:

  • ../../../../../../etc/passwd

Therefore, such values should not be passed directly to the send_download API. If acceptable, the application should generate its own file names and use those. Otherwise, the provided filename should be properly validated to ensure it's properly structured, contains no unauthorized path characters (e.g. / ), and refers to an authorized file.

  1. Go through the issues that GuardRails identified in the PR.

  2. Examples of vulnerable APIs, where the dangerous values are coming from user inputs, are shown below:

    send_download(conn, {:file, dangerous})
    File.read(dangerous)
    File.read!(dangerous)
    File.write(dangerous)
    File.write!(dangerous)
    File.rm(dangerous)
    File.rm!(dangerous)
    File.rm_rf(dangerous)
    File.chmod(dangerous)
    File.chmod!(dangerous)
    File.chown(dangerous)
    File.chown!(dangerous)
    File.mkdir(dangerous)
    File.mkdir!(dangerous)
    File.mkdir_p(dangerous)
    File.mkdir_p!(dangerous)
    File.cp(dangerous, dangerous2)
    File.cp!(dangerous, dangerous2)
    File.cp_r(dangerous, dangerous2)
    File.cp_r!(dangerous, dangerous2)
    File.ln(dangerous, dangerous2)
    File.ln!(dangerous, dangerous2)
    File.ln_s(dangerous, dangerous2)
    File.ln_s!(dangerous, dangerous2)

    Note, that send_download(conn, {:binary, dangerous}) is considered secure

  3. Generally, it is advised not using any user input to access files and file management related APIs as they are very difficult to secure. Each allowed filepath, should be accessible through an indirect list of GUIDs, while assuring that even when knowing the GUID of another user, access is restricted to allowed users.

  4. Ship it 🚢 and relax 🌴

Option B: Migrate to Cloud Storage

Nowadays, there is rarely a need to allow users to interact with local files. A better alternative is storing files in dedicated systems, such as AWS S3. This way attackers can't get access to the local file system.

More information: