What Is Directory Traversal?
Directory traversal — also called path traversal or dot-dot-slash attack — is a vulnerability that allows an attacker to read files from a web server that are located outside the intended web root directory. By manipulating file path parameters in HTTP requests, an attacker can navigate the server's directory structure and access sensitive files: configuration files, credentials, database connection strings, private keys, and even system files.
The name comes from the `../` sequence used in file paths to move up one directory level. By chaining multiple `../` sequences, an attacker traverses from the web application's root directory up through the file system to reach files that were never meant to be accessible via the web.
---
How Directory Traversal Works
Consider a web application that serves files based on a user-supplied filename parameter:
``` https://example.com/download?file=report.pdf ```
The server-side code might construct the file path like this:
```python file_path = "/var/www/uploads/" + request.args.get("file") with open(file_path, "rb") as f: return f.read() ```
An attacker modifies the `file` parameter to traverse outside the uploads directory:
``` https://example.com/download?file=../../../../etc/passwd ```
The constructed path becomes:
``` /var/www/uploads/../../../../etc/passwd ```
Which resolves to:
``` /etc/passwd ```
The server returns the contents of the system's password file. On a Linux server this reveals system usernames. On a poorly configured server, more sensitive files are accessible: `/etc/shadow` (hashed passwords), application configuration files, database credentials, private keys, and source code.
---
Real-World Targets
Once a directory traversal vulnerability is confirmed, attackers typically attempt to read:
**Application configuration files:** ``` ../../../../var/www/html/config.php ../../../../app/config/database.yml ../../../../.env ```
**System files:** ``` ../../../../etc/passwd ../../../../etc/hosts ../../../../proc/self/environ ```
**Web server configuration:** ``` ../../../../etc/nginx/nginx.conf ../../../../etc/apache2/apache2.conf ```
**Application secrets:** ``` ../../../../.ssh/id_rsa ../../../../home/user/.bash_history ```
The `.env` file is particularly valuable to attackers. Modern web applications store database credentials, API keys, session secrets, and third-party service credentials in `.env` files. A single successful traversal to `.env` can expose enough information for a full system compromise.
---
Bypass Techniques
Web application firewalls and naive input filters often attempt to block `../` sequences. Attackers use several bypass techniques:
**URL encoding:** ``` ..%2F..%2F..%2Fetc%2Fpasswd ```
**Double URL encoding:** ``` ..%252F..%252F..%252Fetc%252Fpasswd ```
**Unicode and overlong encoding:** ``` ..%c0%af..%c0%afetc%c0%afpasswd ```
**Mixed separators (Windows targets):** ``` ..\..\..windowswin.ini ../..\..windowswin.ini ```
**Null byte injection (legacy PHP):** ``` ../../../../etc/passwd%00.jpg ```
Appending a null byte followed by a valid extension tricks older PHP versions into ignoring the extension validation while still opening the malicious path.
---
Prevention
**Validate and sanitise file paths server-side:**
```python import os
UPLOAD_DIR = "/var/www/uploads"
def safe_file_path(filename): # Resolve to absolute path requested_path = os.path.realpath(os.path.join(UPLOAD_DIR, filename)) # Ensure it's within the allowed directory if not requested_path.startswith(UPLOAD_DIR + os.sep): raise ValueError("Path traversal detected") return requested_path ```
**Use an allowlist of permitted filenames:**
If the application only serves a known set of files, validate the parameter against that list rather than constructing arbitrary paths:
```python ALLOWED_FILES = {"report-q1.pdf", "invoice-template.pdf", "terms.pdf"}
def get_file(filename): if filename not in ALLOWED_FILES: abort(400) return send_from_directory(UPLOAD_DIR, filename) ```
**Use framework-provided safe file serving functions:**
Most web frameworks provide safe file-serving utilities that perform path validation internally. In Flask, use `send_from_directory` rather than constructing paths manually. In Express, use `express.static` or `res.sendFile` with the `root` option.
**Avoid user-controlled file paths entirely:**
Where possible, design the application so users select from IDs or tokens that map to files server-side, rather than specifying filenames directly:
``` /download?id=abc123 ```
The server maps `abc123` to a specific file path internally, and the user never touches the path.
---
Testing for Directory Traversal
Manual testing involves modifying any parameter that appears to reference a filename or file path. Common parameter names to test:
- `file`, `filename`, `path`, `doc`, `document`, `folder`, `root` - `include`, `require`, `template`, `page`, `view`, `content` - `download`, `upload`, `attachment`, `asset`
Yrzo AI automatically tests for directory traversal vulnerabilities across all parameterised file references discovered during a scan, including URL-encoded and double-encoded bypass variants.
Find out if your website has these vulnerabilities
Yrzo AI runs 44 automated security checks and delivers a full report in under 20 minutes. Starting from £399.
Scan your website →