?language=en.php meant to pick a language file. Walk that path backward with ../ and you’re reading files outside the intended directory. Depending on what the server lets you reach, that ranges from reading /etc/passwd all the way to full remote code execution.
Local File Inclusion (LFI)
Including a file that already exists on the server, outside the intended directory. Starts as information disclosure, often escalates to RCE via wrappers, logs, or uploads.
Remote File Inclusion (RFI)
Including a file from a server you control instead. Immediate RCE if it works, but requires
allow_url_include enabled in PHP, off by default since PHP 5.2.Basic LFI
The simplest case, the parameter takes a path directly with no traversal needed at all.../ repeated enough times to reach the filesystem root.
/ sometimes gets you back to root anyway since the app concatenates paths naively.
Bypassing Traversal Filters
Filter strips '../' once, non-recursively
Filter strips '../' once, non-recursively
Doubling the traversal sequence works against a naive filter that removes
../ only a single pass instead of recursively, since removing the inner ../ leaves a new valid one behind.Filter blocks the literal string '../'
Filter blocks the literal string '../'
URL-encoding the slashes and dots slips past a filter doing a plain string match on Double URL-encoding defeats a filter that decodes once before checking, but the app itself decodes twice.UTF-8 overlong encoding of
../ or /etc/passwd./ can slip past filters on IIS/some WAFs that normalize encoding incompletely.App appends a fixed extension (e.g. '.php') to your input
App appends a fixed extension (e.g. '.php') to your input
Path truncation (obsolete on PHP 5.3+, included for legacy/CTF context): PHP’s old Null byte (obsolete on PHP 5.3.4+): a trailing On a modern PHP version neither trick works, look instead for a wrapper that ignores the extension entirely (see PHP Wrappers below), or a legitimate extension your target path can end with.
MAXPATHLEN handling meant a sufficiently long path with trailing ./ sequences got silently truncated before the appended extension, dropping it entirely.%00 used to terminate the string in C-level string handling, cutting off anything appended after it, including a forced extension.PHP Wrappers for RCE
PHP wrappers are built-in stream handlers (php://, data://, zip://, expect://, and others) that PHP’s file functions can read through instead of a plain path, normally used for things like reading stdin or compressing output. When a parameter controls what gets passed to include() or require(), pointing it at one of these wrappers instead of a real file path lets you feed PHP arbitrary content to execute or decode, turning a file-read bug into code execution. PHP’s stream wrappers can turn a plain LFI into full code execution, each with different requirements.
- php://filter (no config required)
- data:// (needs allow_url_include=on)
- php://input (needs allow_url_include=on)
- expect:// (needs the expect extension)
- zip:// (needs file upload)
Reads a file’s contents through a filter chain rather than including it,
convert.base64-encode is the standard way to safely exfiltrate PHP source without it actually executing (and crashing on syntax it can’t parse as HTML).Remote File Inclusion (RFI)
Ifallow_url_include is on, the parameter will fetch and execute a file from anywhere you point it, including a server you control. Any of these protocols work the same way, host the shell, point the vulnerable parameter at it.
- HTTP
- FTP
- SMB (Windows targets)
LFI + Upload Chains
When RFI is off and the wrappers above don’t apply, combining an upload feature with LFI gets you the same result: get a malicious file onto the disk through any upload field, then include it through the LFI. A GIF magic-byte header in front of the PHP payload is often enough to pass a basic image-type check, and the server still parses the rest of the file as PHP when included.Log and Session Poisoning
When there’s no upload feature at all, poisoning something the server already writes to disk (a log file, a session file) achieves the same effect without needing any upload functionality.PHP Session Poisoning
The session cookie’s value is the session filename on disk, if you can control any value that gets written into your own session data, including that session file executes it.Web Server Log Poisoning
1
Identify the log file path
Common Apache logs:Common Nginx logs:
2
Poison the log via User-Agent
Every request’s User-Agent header gets written verbatim into the access log, including it as PHP.
3
Include the log file to trigger execution
/proc/self/environ (legacy, mod_php only)
/proc/self/environ (legacy, mod_php only)
On older Apache setups running PHP as a module (not PHP-FPM), This technique is well known enough that most modern systems either run PHP-FPM (no
/proc/self/environ holds the process’s environment variables, including the raw HTTP_USER_AGENT value from the request that spawned it. Poisoning the User-Agent the same way as log poisoning, then including this file instead of a log, gets the same result without needing to locate the actual log path./proc/self/environ equivalent exposing the request) or restrict read access to the /proc filesystem, treat it as a fallback worth trying rather than a reliable primary path.Automated Fuzzing
FFUF against a curated LFI payload wordlist covers most common traversal depths and wrapper variants in one pass,-fs filters out the baseline “not found” response size so only real hits show.
Other automated tools
Other automated tools
fimap automates the full LFI/RFI discovery-and-exploitation chain rather than just fuzzing a wordlist:Nuclei has dedicated LFI templates if you want it folded into a broader automated sweep (see Automated Web Scanners):dotdotpwn is an older, dedicated path-traversal fuzzer, still useful for generating encoding-variant payloads automatically:
Quick Reference Tools
Hackviser: LFI/RFI
Reference used for this page.
HackTricks: File Inclusion
Deeper dive into wrappers, filter chains, and edge cases.
SecLists: LFI Wordlists
Wordlists for automated file inclusion fuzzing.
php_filter_chain_generator
Automates building a
convert.iconv filter chain for RCE without upload.fimap
Automated LFI/RFI detection and exploitation.

