This weakness occurs when user-supplied input is used directly to construct file paths without proper validation or restriction. An attacker can manipulate the…
This weakness occurs when user-supplied input is used directly to construct file paths without proper validation or restriction. An attacker can manipulate the path to access files outside the intended directory, read sensitive configuration files, overwrite critical data, or execute arbitrary code. It's one of the most common file-handling vulnerabilities in web applications.
02How It Happens
Applications often need to open, read, or write files based on user input — for example, allowing a user to download a document by name, or upload a file to a specific folder. When the application concatenates user input directly into a file path without checking for directory traversal sequences (like ../), an attacker can escape the intended directory. Even if the application restricts the file extension or checks the filename, insufficient validation of the path itself leaves the door open. The root cause is trusting user input to define or influence where files are accessed on disk.
03Real-World Impact
An attacker exploiting this weakness can read sensitive files such as configuration files containing database credentials, private keys, or source code. They may overwrite application files to inject malicious code, modify user data, or cause denial of service by deleting critical files. In some cases, if the application later executes a file it has written, this can lead to remote code execution. The severity depends on the file permissions and what files are accessible from the application's working directory.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import os
def download_file(filename):
filepath = os.path.join('/var/www/uploads', filename)
with open(filepath, 'rb') as f:
return f.read()
# User requests: download_file('../../../etc/passwd')
# Result: reads /etc/passwd instead of /var/www/uploads/filename
Why it's vulnerable: The filename parameter is concatenated directly into the path without checking for directory traversal sequences. An attacker can use ../ to escape the intended directory.
Fixed pattern
import os
def download_file(filename):
# Whitelist: only alphanumeric, dash, underscore, dot
if not all(c.isalnum() or c in '-_.' for c in filename):
raise ValueError("Invalid filename")
filepath = os.path.join('/var/www/uploads', filename)
# Verify the resolved path is still within the intended directory
if not os.path.abspath(filepath).startswith(os.path.abspath('/var/www/uploads')):
raise ValueError("Path traversal detected")
with open(filepath, 'rb') as f:
return f.read()
Why it's vulnerable: User input from $_GET is directly appended to the base path without validation, allowing ../ sequences to traverse directories.
Fixed pattern
<?php
$filename = $_GET['file'];
// Whitelist: only alphanumeric, dash, underscore, dot
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $filename)) {
die('Invalid filename');
}
$basedir = '/var/www/uploads/';
$filepath = realpath($basedir . $filename);
// Verify the resolved path is within the intended directory
if ($filepath === false || strpos($filepath, realpath($basedir)) !== 0) {
die('Path traversal detected');
}
$content = file_get_contents($filepath);
echo $content;
?>
05Prevention Checklist
Validate file names strictly: Use an allowlist of permitted characters (alphanumeric, dash, underscore, dot). Reject anything else.
Use realpath() or equivalent: Resolve the full path and verify it stays within the intended base directory before opening the file.
Never trust user input for paths: Even if you validate the filename, always check the final resolved path.
Avoid dynamic path construction: If possible, use a mapping table (e.g., user ID → allowed files) instead of building paths from user input.
Apply principle of least privilege: Run the application with minimal file system permissions; restrict what files it can access.
Log and monitor file access: Track unusual file operations (reads outside the uploads directory, access to config files, etc.) to detect attacks early.
06Signs You May Already Be Affected
Check your application logs for requests containing ../, ..%2f, or other path traversal patterns in file-related parameters. Review file access logs for unexpected reads of sensitive files (e.g., /etc/passwd, configuration files, or files outside your intended directories). If you find evidence of unauthorized file reads or modifications, investigate whether user input was used to construct the file path.