Skip to main content
CriticalProtected by PowerWAF

Local File Inclusion (LFI)

CategoryFile & PathOWASPA03:2021 – InjectionFirst seen2001Read time10 minVerified2026-03-11
DEFINITION

Local File Inclusion (LFI) is a vulnerability that allows an attacker to include and read — or in some cases execute — files from the server's local file system through manipulated input parameters. Unlike simple path traversal which only reads file contents, LFI exploits server-side include mechanisms (PHP include(), JSP <%@ include>, SSI), potentially achieving remote code execution by including files that contain attacker-controlled content such as log files, uploaded files, or session data.

How Local File Inclusion (LFI) Works

LFI vulnerabilities occur when applications dynamically include files based on user-controlled input without proper validation. The most common context is PHP applications that use include(), require(), include_once(), or require_once() with user-supplied filenames. When an attacker controls the filename passed to these functions, they can include any readable file on the server. The critical difference from path traversal is that inclusion can mean execution — if the included file contains valid PHP code (even embedded within other content like logs), that code will be executed by the PHP interpreter with the application's full privileges.

1

Identify file inclusion parameters

The attacker searches for URL parameters, form fields, or cookies that influence which files are loaded by the application. Common indicators include parameters like ?page=home, ?template=header, ?lang=en, ?module=dashboard, or ?file=report. These parameters often map directly to file paths on the server (e.g., include($_GET['page'] . '.php')). Testing with non-existent filenames can reveal include-related error messages exposing the file system path.

2

Confirm LFI with known files

The attacker attempts to include known system files to confirm the vulnerability: /etc/passwd on Linux (always readable, confirms traversal depth), C:\Windows\win.ini on Windows, or the application's own configuration files. The payload typically uses directory traversal sequences: ?page=../../../../etc/passwd. If the application appends an extension (e.g., .php), the attacker uses null byte injection (%00 on older PHP versions), path truncation, or PHP wrapper techniques to bypass the extension.

3

Escalate to code execution via log poisoning

The attacker identifies writable files that can be included for code execution. The most common technique is log poisoning: the attacker sends a request with PHP code embedded in the User-Agent header or URL (e.g., <?php system($_GET['cmd']); ?>), which gets written to the web server's access log (/var/log/apache2/access.log). Then, the attacker includes the log file via LFI, causing the PHP code in the log to execute. Other writable targets include /proc/self/environ, PHP session files (/tmp/sess_*), and uploaded temporary files.

4

Exploit PHP wrappers for advanced attacks

PHP provides stream wrappers that enable powerful LFI exploitation: php://filter allows reading source code as base64 (php://filter/convert.base64-encode/resource=config.php), bypassing PHP execution to reveal secrets; php://input allows including POST body as PHP code (requires allow_url_include=On); data:// allows inline code execution; zip:// and phar:// can execute code from crafted archive files. These wrappers transform a simple file read vulnerability into full remote code execution.

5

Achieve persistent access

With code execution established, the attacker deploys a web shell for persistent access: writing a PHP backdoor to the document root, modifying existing application files to include hidden backdoor functions, or establishing a reverse shell connection to the attacker's infrastructure. From this position, the attacker can access databases, steal credentials, pivot to internal networks, install ransomware, or exfiltrate data at scale.

Real-World Examples

2011

TimThumb WordPress vulnerability

A local file inclusion vulnerability in TimThumb, a PHP image resizing script used by thousands of WordPress themes and plugins, allowed attackers to include and execute arbitrary PHP files. Attackers uploaded malicious PHP disguised as images, then included these files through TimThumb's cache mechanism. The vulnerability compromised an estimated 1.2 million WordPress sites, with attackers deploying backdoors, SEO spam, and malware distribution infrastructure.

2012

PHP-CGI parameter injection (CVE-2012-1823)

A vulnerability in PHP's CGI mode allowed attackers to manipulate PHP configuration via query string parameters, enabling file inclusion and remote code execution on any PHP-CGI installation. The vulnerability affected millions of web servers worldwide and was actively exploited within hours of public disclosure. Attackers used it to include and execute arbitrary files, deploying web shells and cryptocurrency miners on compromised servers.

2023

JEECG boot framework LFI (CVE-2023-1454)

A critical LFI vulnerability in JEECG Boot, a popular Java-based low-code development framework used by thousands of enterprise applications, allowed unauthenticated attackers to read arbitrary files from the server. Attackers exploited the vulnerability to extract database credentials, application secrets, and configuration files. The vulnerability was actively exploited in the wild before a patch was available, affecting organizations that had deployed JEECG Boot for internal business applications.

Impact & Risk Assessment

Local file inclusion is rated Critical because it frequently escalates from file reading to full remote code execution. The immediate impact includes reading sensitive configuration files (database credentials, API keys, encryption secrets), application source code, system files (/etc/shadow for password hashes), and private keys. When escalated to code execution via log poisoning, PHP wrappers, or uploaded file inclusion, the attacker gains the ability to execute arbitrary commands with the web server's privileges, typically resulting in complete server compromise. In containerized environments, LFI can expose environment variables containing secrets, Kubernetes service account tokens, and cloud metadata credentials. The prevalence of LFI in PHP applications (which power approximately 77% of all websites) makes it one of the most commonly exploited web vulnerabilities.

How to Detect Local File Inclusion (LFI)

Monitor request parameters for file inclusion indicators: directory traversal sequences (../, ..\), PHP wrapper prefixes (php://, data://, zip://, phar://), null bytes (%00), and references to known sensitive files (/etc/passwd, /proc/self/environ, win.ini). Analyze web server logs for suspicious User-Agent strings containing PHP code (log poisoning indicator). Implement file integrity monitoring on web server log files and session directories — unexpected PHP tags in these files indicate active exploitation. Deploy application-level logging that records all file include/require operations with the resolved file path, flagging any path that falls outside the application's expected directory structure. WAF rules should detect encoded variants of traversal sequences and wrapper syntax. Runtime application self-protection (RASP) can intercept file operations in real-time, blocking includes of files outside the whitelist.

How to Prevent Local File Inclusion (LFI)

Never use user input directly in file inclusion functions. Implement an allowlist of permitted files/modules and map user input to the allowlist via a lookup table (e.g., switch/case or dictionary mapping ?page=home to templates/home.php) rather than using the input as a filename. If dynamic file inclusion is required, resolve the canonical path and verify it falls within the expected base directory. Disable dangerous PHP settings: allow_url_include=Off (prevents remote file inclusion), open_basedir to restrict file access to the application directory, and disable_functions for system(), exec(), passthru(). Use a modern framework that abstracts file inclusion behind safe template rendering (Twig, Blade, Jinja2). Keep PHP and all server-side frameworks updated to patch known LFI vulnerabilities. Deploy a WAF with LFI-specific rules covering traversal patterns, PHP wrappers, and null byte injection. In containerized deployments, apply read-only file systems where possible and minimize the files accessible to the application process.

Code Examples

Vulnerable: Dynamic file inclusion without validation
<?php
// VULNERABLE: User input directly used in include
$page = $_GET['page'];
include("pages/" . $page . ".php");

// Attacker: ?page=../../../../etc/passwd%00
// Result: includes /etc/passwd (null byte truncates .php on old PHP)

// Attacker: ?page=php://filter/convert.base64-encode/resource=config
// Result: Leaks config.php source code as base64

// Attacker: ?page=../../../../var/log/apache2/access.log
// After poisoning User-Agent with: <?php system($_GET['cmd']); ?>
// Result: Remote code execution via log poisoning
?>
Secure: Allowlist-based file inclusion
<?php
// SECURE: Map user input to allowed files via allowlist
$allowed_pages = [
'home' => 'pages/home.php',
'about' => 'pages/about.php',
'contact' => 'pages/contact.php',
'products' => 'pages/products.php',
'faq' => 'pages/faq.php',
];

$page = $_GET['page'] ?? 'home';

// Strict allowlist lookup — no file path manipulation possible
if (!array_key_exists($page, $allowed_pages)) {
http_response_code(404);
include('pages/404.php');
exit;
}

include($allowed_pages[$page]);
?>
LFI detection and prevention middleware
import re
import os
from functools import wraps

# LFI attack patterns
LFI_PATTERNS = [
r'\.\.[\/\\]', # Directory traversal
r'%2e%2e[%2f%5c]', # URL-encoded traversal
r'%252e%252e', # Double-encoded traversal
r'php:\/\/', # PHP wrapper
r'data:\/\/', # Data wrapper
r'zip:\/\/', # Zip wrapper
r'phar:\/\/', # Phar wrapper
r'expect:\/\/', # Expect wrapper
r'%00', # Null byte
r'\/etc\/(passwd|shadow|hosts)', # Known sensitive files
r'\/proc\/self', # Process info
r'\/(var|tmp)\/log', # Log files
r'web\.config', # IIS config
r'\.htaccess', # Apache config
]

def detect_lfi(request_params):
"""Check request parameters for LFI indicators"""
compiled = [re.compile(p, re.IGNORECASE) for p in LFI_PATTERNS]

for param_name, param_value in request_params.items():
decoded = urllib.parse.unquote(urllib.parse.unquote(param_value))
for pattern in compiled:
if pattern.search(decoded):
return {
'detected': True,
'parameter': param_name,
'value': param_value,
'pattern': pattern.pattern
}
return {'detected': False}

def safe_file_resolve(base_dir, user_input):
"""Safely resolve a file path within a base directory"""
# Reject any path separators in user input
if os.sep in user_input or '/' in user_input or '\\' in user_input:
raise ValueError('Invalid filename: path separators not allowed')

# Resolve canonical path
resolved = os.path.realpath(os.path.join(base_dir, user_input))
base_resolved = os.path.realpath(base_dir)

# Verify resolved path is within base directory
if not resolved.startswith(base_resolved + os.sep):
raise ValueError('Access denied: path outside base directory')

if not os.path.isfile(resolved):
raise FileNotFoundError('File not found')

return resolved

PowerWAF automatically blocks Local File Inclusion (LFI) at the edge.

Deploy in minutes. No code changes required. Free plan available.

Free plan spots are limited

Frequently Asked Questions

Path traversal reads file contents by navigating the directory structure — the attacker sees the file's raw content in the response. LFI goes further: it includes the file through the server-side language's include mechanism, which means the file is not just read but potentially executed. If a path traversal lets you read /var/log/apache2/access.log, you see log entries. If an LFI lets you include the same file and you've previously injected PHP code into a log entry, that code executes on the server. LFI is a superset of path traversal with execution capability.
LFI includes files from the local server's file system (../../etc/passwd). RFI includes files from remote URLs (http://attacker.com/shell.php). RFI is more directly dangerous because the attacker controls the included file's content entirely, but it requires allow_url_include=On in PHP (disabled by default since PHP 5.2). LFI is more common because it doesn't require this setting, though escalating LFI to code execution requires additional techniques like log poisoning.
Yes, though PHP is the most common context. LFI affects any language that includes files based on user input: Java/JSP (<%@ include file="..." %>), ASP.NET (Server.Execute, Response.WriteFile), Python (Jinja2 template injection can achieve similar effects), and Server-Side Includes (SSI). Node.js applications that use require() or fs.readFile() with user-controlled paths are also vulnerable, though Node's require() caches modules, limiting some exploitation techniques.
When applications append an extension (include($input . '.php')), older PHP versions (< 5.3.4) could be tricked with null bytes: ?page=../../../../etc/passwd%00. The null byte (%00) terminates the string in C-level functions that PHP uses for file operations, causing .php to be ignored. Modern PHP versions are not vulnerable to null byte injection, but other bypasses exist: path truncation (very long paths), double encoding, and PHP wrapper techniques that render the appended extension irrelevant.
Yes, a WAF provides strong protection against LFI by detecting traversal sequences (../, encoded variants), PHP wrapper patterns (php://, data://), null byte injection, and requests targeting known sensitive file paths. PowerWAF includes comprehensive LFI rules covering standard traversal, URL-encoded and double-encoded variants, Unicode bypass techniques, and PHP-specific wrapper exploitation patterns. However, WAF protection should complement — not replace — secure coding practices like input allowlisting and safe file inclusion patterns.