Path Traversal – Directory Traversal
Complete Reference Guide
1. What Is Path Traversal?
Path Traversal (also called Directory Traversal) is a vulnerability where an attacker tricks the application into reading (or writing) files outside the intended directory on the server.
Normal intent : /var/www/images/product.jpg
Attack : /var/www/images/../../../etc/passwd
Result : /etc/passwd ← a sensitive system file
The ../ sequence means "go up one directory" — repeating it lets you navigate to the filesystem root.
2. Impact
| Impact | Example |
|---|---|
| Reading sensitive files | /etc/passwd, /etc/shadow, configuration files |
| Stealing credentials | Database passwords, API keys in config files |
| Reading source code | Application logic, hardcoded secrets |
| System information | OS version, user lists, network configuration |
| Combined with upload → RCE | Uploading a file + path traversal to execution |
3. Recognizing It — Where Does Path Traversal Risk Live?
Look for parameters that refer to filenames or paths:
| Function | Example parameter |
|---|---|
| Loading images | ?filename=product.jpg |
| Downloading a file | ?file=report.pdf |
| Loading a template | ?template=home.html |
| Log viewer | ?log=access.log |
| Include / import | ?page=about |
| Avatar / profile photo | ?img=user123.png |
Less Obvious
- A
Refererheader with a file path Content-Dispositionin upload responses- API endpoints:
/api/files/{filename} - Path parameters in REST:
/download/invoice-2024.pdf
4. Target Files per OS
Linux / Unix
/etc/passwd ← user list
/etc/shadow ← password hashes (root required)
/etc/hosts ← local DNS
/etc/hostname ← server name
/etc/os-release ← OS version
/proc/version ← kernel version
/proc/self/environ ← environment variables (sometimes creds)
/proc/self/cmdline ← how the app was started
/var/log/apache2/access.log ← Apache access log
/var/log/apache2/error.log ← Apache error log
/var/log/nginx/access.log ← Nginx access log
/home/{user}/.ssh/id_rsa ← private SSH key
/home/{user}/.bash_history ← command history
/root/.ssh/id_rsa ← root SSH key
/var/www/html/config.php ← web application config
/app/config/database.yml ← database credentials
Windows
C:\Windows\System32\drivers\etc\hosts
C:\Windows\win.ini
C:\Windows\System32\config\SAM ← password hashes (requires rights)
C:\inetpub\wwwroot\web.config ← IIS configuration
C:\xampp\htdocs\config.php
C:\Users\Administrator\Desktop\
C:\boot.ini
5. Testing — Step by Step
Step 1 — Identify a Baseline
Find a parameter that contains a file or path:
Send this to Burp Repeater for manual tests.
Step 2 — Simple Traversal
If the response contains the contents of /etc/passwd → Path Traversal confirmed.
Step 3 — Determining Depth
You don't always know how deep the application is in the filesystem. Use enough ../:
Too many ../ isn't a problem — you just stop at the root /.
Step 4 — Testing Absolute Paths
Some applications let absolute paths through if the validation only checks for ../:
Step 5 — Testing Windows Paths
On Windows servers:
6. Bypassing Filters
6a. Stripped ../ Sequences
The application removes ../ from the input but doesn't do this recursively:
Example:
After non-recursively stripping ../:
6b. URL Encoding
..%2F..%2F..%2Fetc%2Fpasswd ← / as %2F
..%252F..%252F..%252Fetc%252Fpasswd ← double encoded
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd ← . and / encoded
%2e%2e/%2e%2e/%2e%2e/etc/passwd
Double encoding is useful if the server decodes twice:
6c. URL Encoding the Backslash (Windows)
6d. Bypassing a Required Base Path
The application requires the path to start with a certain directory:
Bypass:
The validation sees the correct base path, but the traversal neutralizes it afterward.
6e. Bypassing a Required Extension
The application requires a certain file extension (e.g. .jpg):
Null byte injection:
The null byte (%00) terminates the string in some languages (C, old PHP) — the .jpg extension is ignored by the OS.
Note: no longer works in modern PHP (≥ 5.3.4) but still relevant on legacy systems.
6f. Combinations
....%2F....%2F....%2Fetc%2Fpasswd
..%252F..%252F..%252Fetc%252Fpasswd
/var/www/images/../../.%2e/etc/passwd
7. Automatic Detection — Burp Suite
What Burp DOES Detect
- Standard
../traversal in GET/POST parameters (active scan) - Absolute paths (
/etc/passwd) - Basic URL encoding variants
- Known target files as confirmation (looks for
/etc/passwdcontent in the response)
What Burp Doesn't Always Detect
| Blind spot | Reason |
|---|---|
| Traversal in headers | Referer, Cookie are tested less |
| Null byte bypasses | Less common in modern scan templates |
| Double encoding | Not always in scope for the scanner |
| Path parameters in REST | /api/download/../../etc/passwd sometimes missed |
| Application-specific filters | Custom stripping logic is hard to bypass automatically |
8. Burp Intruder — Approach for Filter Bypasses
Use a Path Traversal wordlist as the payload:
Recommended list: SecLists/Fuzzing/LFI/LFI-Jhaddix.txt
Intruder → Sniper
Parameter: filename=§product.jpg§
Payload: LFI wordlist
Filter: Response length deviating from the baseline
9. What to Do After Confirmation?
Path Traversal confirmed
│
├─ /etc/passwd → determine usernames
├─ /etc/shadow → password hashes (if permitted)
├─ ~/.ssh/id_rsa → SSH key exfiltration
├─ Config files → database credentials, API keys
├─ Read source code → look for further vulnerabilities
├─ Log files → log poisoning → RCE
└─ Combine with file upload → RCE
10. Path Traversal → RCE via Log Poisoning
If you can read log files and user input ends up in the logs:
- Send a payload in a header that gets logged:
- Read the log file via path traversal:
- The PHP code in the log gets executed → RCE.
11. Tools
| Tool | Use |
|---|---|
| Burp Suite Pro | Active scan, Repeater, Intruder |
| ffuf | Fuzzing file paths |
| dotdotpwn | A specialized path traversal fuzzer |
| SecLists | LFI/path traversal wordlists (/Fuzzing/LFI/) |
| Burp Logger++ | Filtering responses by file content |
12. Mitigations
- Validate user input — don't allow
../,..%2F, or absolute paths - Use an allowlist of allowed filenames or IDs instead of direct file paths
- Canonicalize the path before validation — use
realpath()or equivalent and check the result falls within the expected base directory - Give the web server minimal filesystem permissions (principle of least privilege)
- Chroot / containerization — restrict the filesystem visible to the application
- Store files via database references or object storage (S3) instead of direct file paths
- Never concatenate filenames directly with a base path without validation