Overview
Facts is an Easy Linux box running Camaleon CMS with a MinIO object storage backend. The attack chain begins with registering an account on the CMS, then exploiting a mass assignment vulnerability in the password change endpoint to escalate the account to admin. As admin, the Filesystem Settings page reveals MinIO (S3-compatible) access and secret keys. Connecting to MinIO exposes an internal bucket containing an SSH private key for the user trivia. After cracking the key’s passphrase with john, SSH access reveals a sudo entry allowing trivia to run /usr/bin/facter as root with no password. Facter’s --custom-dir flag loads arbitrary Ruby code, giving us code execution as root.
Key Attack Chain:
- Register account on Camaleon CMS at
facts.htb - Mass assignment on password change adds
password[role]=adminto escalate to admin - Admin settings reveal MinIO credentials (access key, secret key, endpoint on port 54321)
- MinIO
internalbucket contains SSH private key (id_ed25519) ssh2john+johncracks the passphrase:dragonballz- SSH as
triviausing the cracked key sudo /usr/bin/facter --custom-dir=/tmp/pivwith a malicious Ruby fact escalates to root
Enumeration
Nmap Scan
|
|
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.9p1 Ubuntu 3ubuntu3.2 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.26.3 (Ubuntu)
|_http-title: facts
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Port 80 serves a Camaleon CMS site (“facts”) with trivia content. The admin panel is at /admin/login and registration is available at /admin/register.
Foothold
Account Registration
Register a new account at http://facts.htb/admin/register. The registration form includes a CAPTCHA – note that the CAPTCHA solution must be submitted in lowercase.
Mass Assignment to Admin
After logging in, navigate to the profile edit page at /admin/profile/edit. Intercept the password change request and append &password[role]=admin to the POST body:
_method=patch&authenticity_token=<TOKEN>&password[password]=Password123&password[password_confirmation]=Password123&password[role]=admin
The Camaleon CMS password update endpoint at /admin/users/<id>/updated_ajax does not filter the role parameter, allowing mass assignment to escalate to admin.
Extracting MinIO Credentials
With admin access, navigate to Settings -> General Site -> Filesystem Settings. The page reveals:
- Access Key:
AKIABD5A0D8E111FA5A4 - Secret Key:
4HBeKwNQPxp2DzxyGAWcNesmNxMxGGUiL/Pq/6SP - Bucket:
randomfacts - Endpoint:
http://localhost:54321
SSH Key from MinIO
Connect to MinIO using the mc client:
|
|
[2025-xxx] 0B internal/
[2025-xxx] 0B randomfacts/
Pull the SSH key:
|
|
Cracking the Key Passphrase
|
|
dragonballz (id_ed25519)
The key comment reveals the username: trivia@facts.htb.
SSH Access
|
|
Privilege Escalation
Sudo Enumeration
|
|
Facter Custom Fact Exploit
Facter (Puppet’s system inventory tool) supports loading custom facts from arbitrary directories via --custom-dir. By creating a malicious Ruby fact, we achieve code execution as root:
|
|
For an interactive root shell:
|
|
# id
uid=0(root) gid=0(root) groups=0(root)
Lessons Learned
- Mass assignment vulnerabilities persist – Camaleon CMS did not whitelist permitted parameters on the password change endpoint, allowing role escalation by simply adding
password[role]=adminto the request - Object storage often holds secrets – MinIO/S3 buckets configured for CMS file storage frequently contain sensitive data beyond what the application intended to expose. The
internalbucket held SSH keys - SSH key passphrases are crackable – Weak passphrases like
dragonballzfall quickly to dictionary attacks. Use strong, unique passphrases or hardware-backed keys - Sudo with scriptable tools is dangerous – Facter’s
--custom-dirflag allows loading arbitrary Ruby code, makingsudo facterequivalent tosudo ruby. Tools that support plugin loading should never be given unrestricted sudo access