PortSwigger Walkthrough - File path traversal, sequences stripped non-recursively
Walkthrough of PortSwigger's 'File path traversal, sequences stripped non-recursively' lab.
To browse all labs in this series, visit the full PortSwigger series.
All testing shown in this series is performed against PortSwigger Academy’s intentionally vulnerable labs.
Do not apply these techniques to systems you do not own or have explicit written permission to test.
What’s this?
Stripping ../ from user input is a valid idea, but only if the stripping is applied repeatedly until none remain. A single non-recursive pass can be bypassed by nesting the traversal sequence inside itself: when the inner ../ is removed, the outer characters collapse back into a valid traversal sequence.
The pattern ....// is the standard example. Visually it looks like two dots, two more dots, and two slashes. Reading through it, the substring ../ appears at positions 2-4 (characters ., ., /). After a single stripping pass removes that ../, the remaining characters ., ., / reconstruct a new ../. One pass is not enough.
Objective
The application strips traversal sequences from the filename parameter but only makes a single pass. Use nested sequences to reconstruct the traversal after stripping and read /etc/passwd.
Walkthrough
Catch an image request in Burp’s HTTP history and send it to Repeater. Confirm that a plain ../../../etc/passwd is blocked, then use the nested variant:
1
GET /image?filename=....//....//....//etc/passwd
Walk through what happens on the server: each ....// block contains ../ starting at its third character. The first stripping pass removes those inner ../ sequences, leaving ../ from the outer characters. The resulting string after one pass is ../../../etc/passwd, which the filesystem resolves normally.
The response contains the full contents of /etc/passwd.
Lab solved.

