What is Local File Inclusion (LFI)? Ways to Exploit, Examples and Impact
Explore Local File Inclusion (LFI) mechanics, exploitation techniques like path traversal, and practical mitigation strategies for developers.
Local File Inclusion (LFI) is a critical web security vulnerability that allows an attacker to trick a web application into exposing or running files on the web server. This vulnerability occurs when an application uses a path to a file as input without properly validating it, allowing an attacker to manipulate the input and include files they shouldn't have access to. In this guide, we will dive deep into the technical mechanics of LFI, explore common exploitation techniques, and discuss how to secure your infrastructure against these risks.
Understanding Local File Inclusion (LFI)
Local File Inclusion (LFI) is a type of vulnerability typically found in poorly written web applications. It belongs to the broader category of File Inclusion vulnerabilities, which also includes Remote File Inclusion (RFI). While RFI involves including files from external servers, LFI is restricted to files present on the local server where the application is running.
At its core, LFI happens when an application takes user-supplied input (such as a URL parameter, cookie, or HTTP header) and passes it to a file-system API or a function designed to include files. If the application does not sanitize this input, an attacker can use special characters like ../ (dot-dot-slash) to navigate the directory structure of the server.
Why LFI Happens: The Technical Root Cause
LFI is most commonly associated with server-side scripting languages like PHP, JSP, and ASP. In PHP, for example, functions like include(), include_once(), require(), and require_once() are often used to dynamically load content.
Consider the following PHP code snippet:
<?php
$file = $_GET['page'];
include($file . ".php");
?>
In this example, the developer intends for the user to navigate to index.php?page=contact, which would cause the server to include contact.php. However, because there is no validation on the $file variable, an attacker can manipulate the page parameter to access sensitive system files.
Common LFI Exploitation Techniques
Exploiting LFI requires an understanding of how the target operating system handles file paths. Attackers use various techniques to bypass simple filters and gain access to restricted data.
Path Traversal (Dot-Dot-Slash)
Path traversal is the most basic form of LFI exploitation. By using the ../ sequence, an attacker can "climb" out of the intended directory and access the root filesystem. On Linux systems, a classic target is the /etc/passwd file, which contains a list of system users.
Example Payload:https://example.com/view.php?page=../../../../etc/passwd
If the application is running on Windows, an attacker might target the boot configuration or system initialization files:https://example.com/view.php?page=../../../../windows/win.ini
Bypassing File Extensions with Null Byte Injection
In older versions of PHP (specifically versions prior to 5.3.4), developers often tried to prevent LFI by appending a fixed extension to the user input, as seen in our earlier code example (include($file . ".php");).
Attackers bypassed this using a Null Byte (%00). The Null Byte acts as a string terminator in C-based languages, which PHP uses under the hood. When the file system API sees the Null Byte, it ignores everything following it.
Example Payload:https://example.com/view.php?page=../../../../etc/passwd%00
The server-side logic sees /etc/passwd%00.php, but the filesystem opens /etc/passwd.
Using PHP Wrappers for Data Extraction
Modern LFI exploitation often involves PHP wrappers. These are built-in protocols that allow developers to access various data streams. The most powerful wrapper for LFI is php://filter.
If an attacker wants to read the source code of a PHP file (which would normally be executed and not displayed), they can use the Base64 filter to encode the file content before it reaches the include function.
Example Payload:https://example.com/view.php?page=php://filter/convert.base64-encode/resource=config.php
The server will return a Base64-encoded string of config.php. The attacker can then decode this locally to reveal sensitive information like database credentials or API keys.
Advanced LFI: Escalating to Remote Code Execution (RCE)
While reading files is damaging, the ultimate goal for many attackers is to achieve Remote Code Execution (RCE). LFI can be turned into RCE if the attacker can find a way to write malicious code into a file that the server then includes.
Log Poisoning
Log poisoning is a technique where an attacker injects PHP code into a web server's log files. Most web servers log the User-Agent header of every request. If an attacker sends a request with a malicious User-Agent, that code is written to the log file.
Step 1: Injecting the Payload
An attacker sends a request using a tool like curl:
curl -H "User-Agent: <?php system($_GET['cmd']); ?>" http://example.com/login.php
Step 2: Including the Log File
Now, the attacker uses the LFI vulnerability to include the Apache or Nginx access log. On Linux, this is often found at /var/log/apache2/access.log.
Example Payload:https://example.com/view.php?page=../../../../var/log/apache2/access.log&cmd=id
When the PHP engine processes the log file, it executes the injected system() command, giving the attacker full control over the server.
/proc/self/environ and SSH Auth Logs
On some Linux configurations, the /proc/self/environ file contains environment variables, including the HTTP_USER_AGENT. Similar to log poisoning, an attacker can inject code here. Alternatively, if the attacker can attempt an SSH login with a username containing PHP code, that code may be written to /var/log/auth.log, which can then be included via LFI.
Real-World Impact of LFI Vulnerabilities
The impact of a successful LFI attack ranges from information disclosure to full system compromise.
- Sensitive Data Exposure: Attackers can read
/etc/passwd,/etc/shadow(if permissions allow), and application configuration files (wp-config.php,.env). This often leads to the discovery of database passwords and secret keys. - Session Hijacking: By reading session files stored in
/var/lib/php/sessions/, an attacker can steal active user sessions and impersonate administrators. - Full Server Takeover: As demonstrated with log poisoning, LFI is a common stepping stone to RCE. Once an attacker can execute commands, they can install backdoors, pivot to the internal network, or deploy ransomware.
How to Prevent Local File Inclusion
Preventing LFI requires a defense-in-depth approach. You cannot rely on a single filter, as attackers are constantly finding new ways to bypass them.
1. Implement Strict Input Validation and Whitelisting
The most effective way to prevent LFI is to avoid passing user input directly to filesystem APIs. Instead of allowing any filename, use a whitelist of allowed values.
Secure Code Example:
$allowed_pages = ['home', 'about', 'contact'];
$page = $_GET['page'];
if (in_array($page, $allowed_pages)) {
include($page . ".php");
} else {
include("404.php");
}
2. Use Filesystem Functions Safely
If you must allow dynamic file inclusion, use functions like basename() to strip out directory paths, ensuring that the user can only access files within the intended directory.
$file = basename($_GET['page']);
include("/var/www/html/pages/" . $file);
3. Harden the Server Configuration
Configure your server to limit the impact of a potential vulnerability:
- Disable Wrapper Support: In PHP, set
allow_url_include = Offandallow_url_fopen = Offin yourphp.inifile. - Use open_basedir: The
open_basedirdirective in PHP restricts the files that PHP can access to a specific directory tree, preventing attackers from using../../to reach/etc/passwd. - Least Privilege: Ensure the web server user (e.g.,
www-data) has the minimum necessary permissions. It should not have read access to sensitive system logs or configuration files belonging to other users.
4. Regular Security Audits and Monitoring
LFI vulnerabilities are often hidden in legacy code or complex third-party plugins. Regular automated scanning and manual penetration testing are essential for identifying these flaws before they are exploited.
Conclusion
Local File Inclusion remains one of the most prevalent and dangerous web vulnerabilities. While the basic concept of path traversal is simple, the advanced techniques involving PHP wrappers and log poisoning show how easily a minor oversight can lead to a complete server compromise. By prioritizing input validation, using secure coding patterns, and hardening your server environment, you can significantly reduce your risk profile.
To proactively monitor your organization's external attack surface and catch exposures before attackers do, try Jsmon.