Local File Inclusion (LFI)
Before we examine Local File Inclusion,
let’s take a moment to explore the differences
between File Inclusion and Directory Traversal.
These two concepts often get mixed up
by penetration testers and security professionals.
If we confuse the type of vulnerability we find,
we may miss an opportunity to obtain code execution.
As covered in the last Learning Unit,
we can use directory traversal vulnerabilities
to obtain the contents of a file outside of the web server’s web root.
File inclusion vulnerabilities
allow us to “include” a file in the application’s running code.
This means we can use file inclusion vulnerabilities
to execute local or remote files,
while directory traversal only allows us to read the contents of a file.
Since we can include files in the application’s running code
with file inclusion vulnerabilities,
we can also display the file contents of non-executable files.
For example,
if we leverage a directory traversal vulnerability in a PHP web application
and specify the file admin.php,
the source code of the PHP file will be displayed.
On the other hand,
when dealing with a file inclusion vulnerability,
the admin.php file will be executed instead.
In the following example,
our goal is to obtain Remote Code Execution via an LFI vulnerability.
We’ll do this with the help of Log Poisoning.
Log Poisoning works by modifying data we send to a web application
so that the logs contain executable code.
In an LFI vulnerability scenario,
the local file we include is executed if it contains executable content.
This means that if we manage to write executable code to a file
and include it within the running code,
it will be executed.
In the following case study,
we’ll try to write executable code to Apache’s log file.
We’ll first need to review what information is controlled by us
and saved by Apache in the related log.
In this case,
“controlled” means that we can modify the information
before we send it to the web application.
Let’s use curl to analyze which elements comprise a log entry
by displaying access.log using the previously-found LFI vulnerability.
This means we’ll use the relative path of the log file
in the vulnerable “page” parameter
in the “Mountain Desserts” web application.
The output shows that the User Agent is included in the log entry.
Before we send a request,
we can modify the User Agent in Burp
and specify what will be written to the log file.
Apart from the specified file,
this command is equivalent to the directory traversal attack
from the previous Learning Unit.
The exploitation of directory traversal and LFI vulnerabilities
mainly differs when handling executable files or content.
Let’s start Burp,
open the browser,
and navigate to the “Mountain Desserts” web page.
We’ll click on the Admin link at the bottom of the page,
then switch back to Burp and click on the HTTP history tab.
Let’s select the related request and send it to Repeater.
We can now modify the User Agent to include a PHP code snippet.
This snippet accepts a command via the cmd parameter
and executes it via the PHP system function on the target system.
We’ll use echo to display command output.
After modifying the User Agent,
let’s click Send.
The PHP code snippet was written to Apache’s log file.
By including the log file via the LFI vulnerability,
we can execute the PHP code.
To execute our snippet,
we’ll first update the page parameter
in the current Burp request with a relative path.
We also need to add the cmd parameter
to the URL to enter a command for the PHP snippet.
We’ll use the ps command to verify that the log poisoning is working.
Since we want to provide values for the two parameters,
we can use an ampersand as a delimiter.
We’ll also remove the User Agent line
from the current Burp request to avoid poisoning the log again,
which would lead to multiple executions of our command
due to two PHP snippets being included in the log.
After sending our request,
let’s scroll down and review the output in the Response section.
Our ps command executed successfully.
Let’s update the command parameter with ls -la.
The output in the Response section shows that our input triggers an error.
This happens due to the space between the command and the parameters.
There are different techniques we can use to bypass this limitation,
such as using Input Field Separators or URL encoding.
With URL encoding, a space is represented as “%20”.
Let’s replace the space with “%20” and press Send.
This time, our command executed correctly.
We have achieved command execution on the target system
and can leverage this to get a reverse shell
or add our SSH key to the authorized_keys file for a user.
Let’s attempt to obtain a reverse shell by adding a command to the cmd parameter.
We can use a common Bash TCP reverse shell one-liner.
Since we’ll execute our command through the PHP system function,
we should be aware that the command may be executed via the Bourne Shell,
also known as sh,
rather than Bash.
Our reverse shell one-liner
contains syntax that is not supported by the Bourne Shell.
To ensure the reverse shell is executed via Bash,
we need to modify the reverse shell command.
We can do this by providing the reverse shell one-liner
as argument to bash -c,
which executes a command with Bash.
We’ll once again encode the special characters with URL encoding.
Before we send the request,
let’s start a Netcat listener on port 4444 on our Kali machine.
It will receive the incoming reverse shell from the target system.
Once the listener is started, we can press Send to send the request.
We successfully received the reverse shell in our Netcat listener
and now have an interactive shell on the target.