Path Traversal: The Art of Escaping the Filesystem Prison
Welcome, security engineers, bug hunters, and people who still think ../ is harmless.
If SQL Injection is about betraying your database, then Path Traversal is about betraying your filesystem. It’s the vulnerability that turns “Here’s a file you’re allowed to see” into “Here’s literally everything on the server — enjoy.”
No magic. No zero-days. Just dots. Slashes. And developer trust.
This article is not a quick overview. This is the Path Traversal Hall of Fame — how it works, how it’s exploited in the real world, how developers keep re-introducing it, and how attackers chain it into full compromises.
If you’ve ever written something like:
open("/app/files/" + user_input)
This article is about you.
What Is Path Traversal? (The Filesystem Betrayal)
Path Traversal (also called Directory Traversal) is a vulnerability that allows an attacker to access files and directories outside the intended directory by manipulating file paths.
The core idea is painfully simple:
The application trusts user input to stay inside a folder. The attacker teaches it how to walk out.
The Mental Model
Every Path Traversal bug follows this flow:
User Input → Path Construction → Filesystem Trust → Disaster
The application assumes:
- The user will request valid filenames
- The filesystem will “do the right thing”
-
../is someone else’s problem
The filesystem, of course, does exactly what it’s told.
The One-Line Bug That Breaks Everything
Let’s start with the smallest possible mistake.
filename = request.args.get("file")
with open("/app/files/" + filename) as f:
return f.read()
Developer intention:
-
Serve files from
/app/files/
Attacker input:
file=../../../../etc/passwd
Final resolved path:
/etc/passwd
No exploit framework. No memory corruption. Just string concatenation.
Why Path Traversal Is So Dangerous
Path Traversal is underestimated because it looks “read-only”. In reality, it often leads to:
-
Reading sensitive files (
/etc/passwd,.env, configs, source code) - Credential disclosure (DB passwords, API keys, tokens)
- Local File Inclusion (LFI)
- Remote Code Execution (via log poisoning, uploads, or templates)
- Privilege escalation
- Container and cloud secret leaks
Path Traversal is rarely the end of an attack. It’s usually the first unlocked door.
The Attacker’s Toolkit: How Traversal Actually Works
The Classic Payloads
-
../→ move up one directory -
../../../../→ move up a lot -
..\→ Windows traversal -
Absolute paths:
/etc/passwd,C:\Windows\win.ini
Encoding Tricks
Attackers don’t stop at ../.
-
URL encoding:
%2e%2e%2f -
Double encoding:
%252e%252e%252f -
Mixed encoding:
..%2f -
UTF-8 overlong sequences (legacy):
..%c0%af
Why Filtering Fails
Blocking "../" does nothing when:
- The server decodes twice
- The framework normalizes late
- The OS handles paths differently
-
Windows accepts both
/and\
Blacklists lose. Every time.
Types of Path Traversal (The Full Spectrum)
1. Basic Path Traversal
The textbook case.
file=../../../../etc/passwd
Still works in 2026. Still appears in production.
2. Encoded Traversal
Filters check raw input, filesystem sees decoded output.
file=%2e%2e%2f%2e%2e%2fetc%2fpasswd
3. Double-Decoding Traversal
Common in:
- Reverse proxies
- Legacy frameworks
- Misconfigured middleware
file=%252e%252e%252fetc%252fpasswd
Decoded twice → ../etc/passwd
4. Windows-Specific Traversal
Windows is generous.
..\..\windows\win.ini
Also works with:
- Mixed slashes
- Case variations
- UNC paths
5. Null Byte Injection (Legacy but Real)
Old PHP / C-based systems:
../../etc/passwd%00.png
The app thinks it’s an image. The OS stops at the null byte.
6. Zip Slip (Traversal by Archive)
Traversal inside compressed files.
../../../../var/www/html/shell.php
When extracted? Files land outside the intended directory.
This one caused real-world RCEs at scale.
7. Symlink Traversal
Upload a symlink → access it like a normal file.
uploads/report.pdf → symlink → /etc/shadow
The app checks the path. The filesystem follows the link.
Attack Vectors: Where Traversal Hides
Path Traversal doesn’t live only in /download.
1. GET Parameters
/download?file=report.pdf
Classic. Dangerous.
2. POST Data
Hidden in forms, JSON, or multipart requests.
3. API Endpoints
/api/export?path=users/2024.csv
APIs are prime targets.
4. HTTP Headers
-
User-Agent -
Referer -
X-Filename
Anything logged or reused later.
5. File Uploads
Filename-controlled paths:
filename=../../shell.php
6. Backup / Export Features
“Download your data” features are traversal goldmines.
Real-World Path Traversal Hall of Fame
1. Apache Tomcat (CVE-2017-12615)
What happened: Tomcat allowed path traversal in PUT requests.
Impact:
- Upload files outside web root
- Drop web shells
- Full server compromise
Lesson: Filesystem bugs turn into RCE fast.
2. Zip Slip (2018)
What happened: Archive extraction without path validation.
Affected:
- Jenkins
- Nexus
- Thousands of Java, Python, Go projects
Impact: Remote code execution by uploading a zip file.
Lesson: Traversal isn’t always user-visible.
3. Steam Client (2019)
What happened: Path traversal in update logic.
Impact:
- Arbitrary file overwrite
- Privilege escalation to SYSTEM
Lesson: Traversal isn’t just a web bug.
4. Fortnite Launcher
What happened: Improper path handling in Windows installer.
Impact:
- Arbitrary file overwrite
- Malware persistence
5. NASA Public API
What happened: Traversal in API paths.
Impact:
- Internal configs exposed
- Credentials leaked
Lesson: APIs don’t get a free pass.
Vulnerable Code: The Hall of Shame
PHP – The Classic Mistake
$file = $_GET['file'];
readfile("/var/www/files/" . $file);
Attack:
file=../../../../etc/passwd
Python – Flask Disaster
filename = request.args.get("file")
open("/app/files/" + filename)
Node.js – Express Mess
res.sendFile("/app/files/" + req.query.file)
Java – Servlet Slip
new FileInputStream("/app/files/" + file);
C# – .NET Nightmare
PhysicalFile("/app/files/" + file);
Go – Fast but Fragile
ioutil.ReadFile("/app/files/" + file)
Same bug. Different language. Same result.
Advanced Exploitation: When Traversal Grows Teeth
1. LFI → RCE (Log Poisoning)
- Inject code into logs via User-Agent
- Traverse to log file
- Include it
- Code execution
2. Traversal + Upload = Game Over
Upload:
filename=../../shell.php
Then access it normally.
3. Traversal in Containers
Docker doesn’t save you.
- Mounted secrets
-
/proc/self/environ - Kubernetes tokens
Traversal still works inside the container’s view.
4. Cloud Secrets Leakage
-
.env - AWS credentials
- GCP service accounts
- Mounted volumes
Traversal loves cloud apps.
Defense: How to Actually Fix Path Traversal
1. Stop Concatenating Paths
If you remember nothing else, remember this.
2. Whitelisting (Not Blacklisting)
ALLOWED = {"report.pdf", "manual.pdf"}
if filename not in ALLOWED:
abort(403)
3. Path Normalization + Verification
base = "/app/files"
full = os.path.normpath(os.path.join(base, filename))
if not full.startswith(base):
abort(403)
4. Use Safe Framework APIs
-
Flask:
send_from_directory -
Node:
path.resolve -
Java:
Paths.get().normalize()
5. Least Privilege
Your app should not:
-
Read
/etc - Read source code
- Run as root
6. Sandboxing
- Docker (properly)
- AppArmor
- SELinux
- Read-only mounts
7. WAF Is Not Enough
WAFs:
- Miss encodings
- Miss logic bugs
- Can be bypassed
Defense must be in code.
Testing for Path Traversal Like a Pro
Manual Mindset
Ask:
- “Where is user input used as a path?”
- “Where do files come from?”
- “Where do files go?”
Payloads to Try
../
../../
..%2f
%2e%2e%2f
%252e%252e%252f
..\
/etc/passwd
C:\Windows\win.ini
Tools
- Burp Suite
- OWASP ZAP
- ffuf
- Custom scripts
Code Review Grep Targets
-
open( -
readFile -
send_file -
sendFile -
FileInputStream -
ioutil.ReadFile
Common Developer Myths
- “We filtered ../”
- “It’s behind auth”
- “It’s internal”
- “It’s just read-only”
- “The framework handles it”
Attackers love these sentences.
Final Thoughts
Path Traversal is not flashy. It doesn’t look like an exploit. It doesn’t feel advanced.
And that’s exactly why it keeps working.
Every time you trust user input with the filesystem, you’re handing over a map and hoping the user doesn’t know how directories work.
They do.
Normalize paths. Whitelist aggressively. Assume the attacker knows the filesystem better than you.
Because most of the time — they do.
Recommended Next Steps
If you want Path Traversal to move from “I understand it” to “I can reliably find and break it”, here’s what to do next.
-
Set up vulnerable labs
- DVWA (Directory Traversal + File Inclusion modules)
- WebGoat (Path Traversal lessons)
- OWASP Juice Shop (file access & API abuse)
- Custom mini-apps with unsafe file download/upload endpoints
-
Practice in real environments
- Hack The Box (machines with LFI / traversal chains)
- TryHackMe (Directory Traversal & File Inclusion rooms)
-
Focus on
chaining
, not just reading
/etc/passwd
-
Practice mindset, not payloads
- Look for where user input becomes a path
- Look for exports, backups, logs, uploads
- Always ask: “What happens if I walk out of this directory?”
-
Study real-world incidents
- Zip Slip post-mortems
- Tomcat traversal CVEs
- Client-side traversal bugs (Steam, launchers, installers)
- Cloud and container traversal writeups
-
Audit real code
-
Grep codebases for
open(),readFile(),sendFile() - Review any place paths are constructed manually
- Review archive extraction logic carefully
-
Grep codebases for
-
Harden your own projects
- Remove all path concatenation
- Enforce strict whitelists
- Apply least privilege at the filesystem level
- Log and alert on traversal attempts
-
Think beyond the web
- Desktop apps
- Installers and updaters
- CI/CD pipelines
- Containerized workloads
-
Make filesystem security part of your SDLC
- Code review checklists
- Security tests for file access
- Developer education on traversal risks
References
- OWASP. Path Traversal . https://owasp.org/www-community/attacks/Path_Traversal
- OWASP Cheat Sheet Series. File Upload and Path Traversal Defense . https://cheatsheetseries.owasp.org/
- PortSwigger Web Security Academy. File Path Traversal . https://portswigger.net/web-security/file-path-traversal
- Snyk Research. Zip Slip Vulnerability . https://snyk.io/research/zip-slip-vulnerability
- CWE-22. Improper Limitation of a Pathname to a Restricted Directory . https://cwe.mitre.org/data/definitions/22.html
- Apache Tomcat CVE-2017-12615 Analysis. https://nvd.nist.gov/vuln/detail/CVE-2017-12615
- PayloadsAllTheThings. Directory Traversal . https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Directory%20Traversal
- NIST Special Publication 800-53 (Rev. 5). Security and Privacy Controls . https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final
- Krebs on Security. Breach Analysis & Post-Mortems . https://krebsonsecurity.com/