Monday, April 20, 2015

PlaidCTF - qttpd - Pwnable Part 1 200 Point Challenge

Feels like such a long time from the last CTF I did! Since NDH I looked a little bit at ExodusCTF but didn't have too much luck only solving a few of the easy ones like killing the bear so nothing to really write up. So PlaidCTF was really good for me to get back into CTFing.

I started on qttpd as it was one of the earliest challenges available. It was in the Pwnable category but was a challenge in three parts with part one being more of a web challenge.

What we had was a link to a website. The website was for a fictitious travel destination with several subpages that were called using a page= variable given in the URL. A URL Such as/?page=index would give us the home page.

First thoughts whenever you see a page= variable in a url is that there's probably a local file inclusion vulnerability there, so why not give that a shot? Also, since we didn't know what file to include yet we started with an empty directory traversal attempt to see if we needed to work around some input validation or something. The URL we tried first was /?page=../../..

Fortunately our first guess paid off in two ways. We found minimal input validation (well none that mattered for the challenge) and actually our first attempt rewarded us by showing that the script was able to mistakenly open a directory as a file and give us some binary data showing the files and folders that exist within the webservers filesystem,

You can see an example below:

Ok, that's cool so a couple of interesting items here, flags for one. We tried to get those using the directory traversal / file include but no luck so that might just be a red herring for now. Let's look at the other files here. Looks like:

.

..

httpd.conf

httpd.stripped

.profile

lastlogin

errors

uploads

www

includes

flag1/2/3.jpg

Some folders probably, some files too, if we can get that httpd.stripped and httpd.conf we can know more about the environment we're targeting. Let's try and get them...

Cool, we learned a little there, chroot environment, the uploads folder we sort of already knew about, timeout values, flag folders that we couldn't access. What about the binary:

Ok sweet. using this URL we could download the binary, we did this using wget on a Kali box and edited the extra html junk out to recover the ELF file. We'll check that a bit later. In the meantime let's keep probing around the filesystem.

After a little more probing we start to find less and less of interest. The includes/ folder was not directly readable like the root folder was so we have less and less to go on. I decided to start switching over to the local file inclusion part of this testing phase.

One of the first things I try is to include the index file itself. I had already learnt during my testing so far that this site uses SHTML file extensions on all the pages. This is divulged in the error messages such as: File not found (../pages/../includes/.shtml) . What happens if i ask the server to include itself in its index.shtml output?

/?page=../www/index.shtml output:

Cool! We get the source code of the service side script including details about something called a SCRIPT_EXT and a path to other juicy loot. "../includes/base.inc". Let's read that if we can:

/?page=../includes/base.inc output:

And one more file we can read from that, ../includes/error.inc, whats that?:

Ok so now we're beginning to form the basis of our attack, let's combine what we found out.

We found that there exists a variable SCRIPT_EXT and if we can control this we can control the extension of the file considered to be a script for execution

We can traverse the directories and read any file within the chroot environment as long as we know the exact path to it.

We're beginning to learn something about a file in POST_PATH? What's that all about? We'll learn later.

We see that if we can invoke an error and have DEBUG set to on, we can get the system to call a function called var_dump()? Sounds promising.

Let's look into that last one first. It seems logical that to get error.inc to run we can just call in directly right? We'll need to use that SCRIPT_EXT variable to get this trick to work:

/?page=../includes/error&SCRIPT_EXT=.inc

This reveals nothing in the page itself but when we view source we see the error message. So that confirms we can control variables in the scripting language from the GET request:

And what about with DEBUG turned on?

Cool stuff but not everything we need yet. We need to switch to a POST query and probably something of type "application/x-www-form-urlencoded" which we learned about in the "base.inc" file. From here I switch to using curl in my Kali box:

Ok look at that, seems like there's that POST_PATH variable we read about. Let's see, can we just browse to that folder and look at our contents?

File not found (../pages/../uploads/E713E9DC16497//data1d2fc014.0)
Nope. In fact, in my testing I was unable to ever get directly to this file once I learned about it's name. If the file was stored on the server any length of time I think it must be a few seconds at the most.

Let's learn about how this filename is created? For that we switch to the httpd.stripped binary we downloaded earlier. A little reversing gives us the following part of a function:

So the upload path name is a function of the current time plus whatever the tempnam(3) function comes up with. The timing of the naming scheme isn't very fine though, so quite predictable. Great!

So in order to attack this I decided to stop trying to access folders we knew existed in the past but to predict what folder will exist during my next call and call for it at the same time I create it. We might not hit it exactly so trial and error might be needed.

So what? Why attack this folder at all?

Well so far we've not come across much in the way of useful files to include as vectors for injecting commands. We know there's a server side scripting language but we don't have any way thus far to perform command injection.

Along the way we tried various methods of injecting data. The contact form for example was a nice distraction but ultimately proved useless for injection.

The theory we've been building on is based on some learnings from reversing the httpd.stripped binary. What it seems to do is take the POST payload data and store it in this POST_PATH data file for processing.

This gives us an injection vector, however brief, where we can control data stored on the server.

So this is the overview of the attack we plan:

Send a POST query, gather intel about the current POST_PATH on the server

Based on the return value, guess what the POST_PATH will be in a few seconds from now

Build a weaponised payload with script commands

Repeatedly query our guessed POST_PATH using the correct SCRIPT_EXT to enable execution until it works

We have everything we need now except a weaponised payload. We need to learn about the scripting language used. For this we use what we know from the example source code we've seen so far in base.inc, error.inc and index.shtml:

Script commands are enclosed in <@ @> and commands are terminated with semicolons