The lab
here is how portswigger describes it
This lab contains a path traversal vulnerability in the display of product images.
The application validates that the supplied filename ends with the expected file extension.
To solve the lab, retrieve the contents of the /etc/passwd file.
the last lab checked the start of our path, so we started where it wanted and wandered off. this one checks the opposite end, it insists the filename finishes with an image extension. the way through is a very old trick that makes the check and the file system disagree about where our string actually ends.
why checking the extension can be fooled?#
this app validates that the filename ends with something like .png, on the assumption that if a path finishes in an image extension it must be harmless. that reasoning falls apart because of a mismatch between the language the application is written in and the operating system underneath it.
the gap is the null byte, written %00 in a url. in many older languages a string is just a run of characters with a length, so ../../../etc/passwd%00.png is one long string that genuinely ends in .png, and the extension check is satisfied. but the underlying system calls are written in C, where a string ends at the first null byte it meets. so when that same value is handed down to actually open the file, C reads it only up to the %00 and treats everything after as if it were not there. the application thinks the name ends in .png, the file system thinks it ends at passwd, and we solve the lab inside that disagreement.
Step 1 - Append a null byte before the required extension#
this is the same image endpoint as every lab in the series, so we intercept the request and send it to repeater to craft the payload.
we build a normal traversal path to the target, then tack on a null byte followed by the extension the validator demands:
../../../etc/passwd%00.png
the two halves do two different jobs. the %00.png on the end exists purely to get past the check, since the application scans the whole string, sees it terminates in .png, and approves it. then when the path drops down to the file system, the null byte cuts the string short, so the part that actually gets opened is just ../../../etc/passwd. the .png was only ever there to please the validator and it never reaches the file read.

so the traversal sequence climbs to the root and lands on the target, while the extension that was supposed to keep us penned in gets discarded before it matters.
the response returns the full contents of /etc/passwd.

with this, the lab is solved!
