DEV Community

Golam_Mostafa
Golam_Mostafa

Posted on

Securing File Paths: Preventing Directory Traversal Attacks

Improper handling of file paths can lead to security vulnerabilities known as directory traversal attacks. These vulnerabilities allow an attacker to access arbitrary files on the server.

What is a Directory Traversal Attack?

A directory traversal attack occurs when an attacker manipulates file paths to access files outside the intended directory. For instance, if an application uses a user-provided file path without validation, an attacker could use a path like ../../etc/passwd to access sensitive files on the server.

Example of a Directory Traversal Attack:

  1. Vulnerable Code:
const filePath = `public/uploads/${req.params.fileName}`;
Enter fullscreen mode Exit fullscreen mode

Imagine you have a file download function that allows users to download files by providing an id. The application might construct the file path directly from the user input.

  1. Malicious Input:
/public/uploads/../../secret.txt
Enter fullscreen mode Exit fullscreen mode

Here an attacker could provide a malicious input like ../../secret.txt, leading to an unintended file access.

  1. Consequences:

If the application does not validate this input, it could expose sensitive files, such as configuration files or user data, to the attacker.

Example of preventing such kind of attacks

import path from 'path';
import fs from 'fs/promises';
import { RequestHandler, NextFunction } from 'express';

// Point: 1
const BASE_DIRECTORY = path.resolve(__dirname, 'public/uploads');

export const downloadAttachment: RequestHandler = async (req, res, next: NextFunction) => {
    // Point: 2
    const { fileName } = req.params; 

    // Point: 3
    const filePath = path.join(BASE_DIRECTORY, fileName);
    const resolvedPath = path.resolve(filePath);

    // Point: 4
    if (!resolvedPath.startsWith(BASE_DIRECTORY)) {
        return res.status(400).json({ message: "Invalid file path" });
    }

    try {
        // Point: 5
        await fs.access(resolvedPath);

        // Point: 6
        res.download(resolvedPath, path.basename(fileName), (err) => {
            if (err) {
                return next(err);
            }
        });
    } catch {
        // Point: 7
        return res.status(404).json({ message: "File not found" });
    }
};
Enter fullscreen mode Exit fullscreen mode

Key Points Explained:

  1. Base Directory Definition: Establishes a fixed directory for file uploads to restrict access.

  2. Extracting File Name: Retrieves the requested file name from the URL parameters.

  3. File Path Construction: Combines the base directory with the requested file name to create a full path.

  4. Path Validation: Ensures that the resolved file path is within the designated base directory to prevent unauthorized access.

  5. File Existence Check: Asynchronously checks if the file exists at the constructed path.

  6. File Download Handling: Initiates the file download and handles any errors that may occur during the process.

  7. Error Handling for Missing Files: Sends a 404 response if the requested file does not exist.


Acknowledgment: This document references information from PortSwigger Web Security and ChatGPT.


Sentry blog image

How to reduce TTFB

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

In this article, we’ll see how we can identify what makes our TTFB high so we can fix it.

Read more

Top comments (0)

Cloudinary image

Zoom pan, gen fill, restore, overlay, upscale, crop, resize...

Chain advanced transformations through a set of image and video APIs while optimizing assets by 90%.

Explore