Directory Traversal Detection
Directory traversal reads files from the server filesystem by manipulating file path parameters. Unlike local file inclusion (LFI), which includes and executes a file through the application's interpreter (PHP include(), Python import), traversal reads raw file contents without execution. The distinction matters: traversal is language-agnostic and works against any application that passes user input into a filesystem read operation. LFI is a subset that additionally executes the included file, making it more dangerous in PHP and similar environments but limited to those runtimes. Both start the same way: finding a parameter that references a file path. For the closely related file inclusion detection techniques (LFI/RFI with encoding bypasses and automated fuzzing), and the full file inclusion exploitation chain (log poisoning, PHP wrappers, RCE), see the dedicated pages.
Identifying Suggestive Parameters
Look for parameters that likely map to filesystem paths. Common names include file, path, doc, document, download, img, image, template, page, load, resource, include, dir, folder, content, and view. Any parameter whose value looks like a filename or path segment deserves testing. Check both GET query parameters and POST body parameters. Also inspect cookie values and HTTP headers like X-Forwarded-File or custom application headers. Parameters with values like report.pdf, en/about, or images/logo.png are strong indicators.
Relative Path Traversal
Relative traversal uses ../ sequences to step out of the intended directory and reach files elsewhere on the filesystem. The number of ../ sequences needed depends on how deep the current working directory is. Using more sequences than necessary does not cause errors because the filesystem stops at the root directory. Start with a deep traversal and confirm the file reads correctly.
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
If the application strips or blocks ../ literally, try URL-encoded variations. Single encoding (%2e%2e%2f or ..%2f) bypasses filters that check the raw string before URL decoding. Double encoding (%252e%252e%252f or ..%252f) works when the application decodes the input twice, which happens with certain proxy and framework configurations.
Absolute Path Traversal
Some applications do not restrict the parameter to a relative path. If the application reads whatever value you supply as a full filesystem path, no traversal sequences are needed. Supply the absolute path directly.
root:x:0:0:root:/root:/bin/bash
[fonts] [extensions] [mci extensions] [files]
Filter Bypass Techniques
Applications commonly implement input filters to block traversal attempts. Each filter type has known bypasses.
Nested traversal defeats filters that strip ../ once without recursion. After the filter removes the inner ../, the remaining characters form a new ../ sequence.
Null byte injection worked against older PHP versions (before 5.3.4) and some legacy applications. The null byte terminates the string in C-level filesystem functions, stripping any suffix the application appends (like .php or .png).
Mixed encoding and path variations combine different encoding styles to evade pattern matching. Backslash substitution works on Windows where both / and \ are valid path separators. UTF-8 overlong encoding (%c0%ae for .) bypasses some WAF rules. Try all variations when basic traversal is blocked.
OS-Specific Targets
After confirming traversal works, target files that yield actionable information. The files you read first depend on the target OS.
Linux Targets
/etc/passwd confirms the vulnerability and lists system users. /etc/shadow contains password hashes but requires root-level read access, which most web applications do not have. /proc/self/environ exposes environment variables for the web server process, often containing database credentials, API keys, and secret tokens. Application config files are the highest-value targets after confirming the vulnerability works.
PATH=/usr/local/sbin:/usr/local/bin DB_HOST=localhost DB_USER=app DB_PASS=s3cr3t SECRET_KEY=a1b2c3d4e5f6
APP_KEY=base64:abc123... DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_DATABASE=app DB_USERNAME=root DB_PASSWORD=p@ssw0rd
Other high-value Linux files: /etc/hosts (internal hostnames), /proc/self/cmdline (running process command line), /home/<user>/.ssh/id_rsa (SSH private keys), /var/log/apache2/access.log or /var/log/nginx/access.log (useful for log poisoning to LFI escalation), and /etc/apache2/sites-enabled/000-default.conf or /etc/nginx/sites-enabled/default (reveals document root paths and virtual host configurations).
Windows Targets
C:\Windows\win.ini is the standard proof-of-concept file for Windows traversal. C:\inetpub\wwwroot\web.config contains IIS application settings including database connection strings. C:\Windows\System32\drivers\etc\hosts reveals internal hostnames. C:\Users\<user>\.ssh\id_rsa may contain SSH keys if OpenSSH is installed.
<connectionStrings> <add name="DB" connectionString="Data Source=db.internal;Initial Catalog=app;User ID=sa;Password=DBp@ss123" /> </connectionStrings>
Directory Listing
Misconfigured web servers expose directory contents when no index file exists. This is not traversal but provides similar information: filenames, backup files, configuration files, and application structure.
Apache enables it with Options +Indexes in .htaccess or the virtual host config. Nginx uses autoindex on in the location block. IIS has a "Directory Browsing" feature that can be enabled per-directory. Look for it on any path that returns an HTML page listing files rather than a 403 or custom error page.
Directory listing reveals backup files (.bak, .old, .swp), configuration files left in the webroot, source code archives (.zip, .tar.gz), and temporary files that developers forgot to remove. Each discovered file is a potential information disclosure or a starting point for further exploitation.
200 / 200 /images/ 403 /uploads/ 200 /backup/ 403 /admin/ 404 /config/ 200 /includes/ 200 /assets/ 200 /static/
Explain command
| -s | Silent mode, suppress progress output. |
| -o /dev/null | Discard response body, only check status. |
| -w '%{http_code}' | Print only the HTTP status code. |
A 200 response on a directory path that returns HTML with file listings confirms directory browsing is enabled. Manually inspect each 200 response to check whether it returns actual directory contents or a default page. Pay attention to 403 responses on /uploads/ and /admin/ as they confirm the directory exists even though listing is blocked.
References
-
OWASP: Path TraversalLINK: OWASP: Path Traversal, owasp.org/www-community/attacks/Path_Traversal (opens in new tab)
Traversal attack patterns and prevention techniques.
-
PortSwigger: File Path TraversalTOOL: PortSwigger: File Path Traversal, portswigger.net/web-security/file-path-traversal (opens in new tab)
Traversal labs covering filter bypasses and encoding variations.