Lost Tape

Máquina LostTape de Vulnyx

LostTape

Info

Nombre
DIficultad
Ip
Plataforma

LostTape

Medium

172.16.243.135

Reconocimiento

Comenzamos con un escaneo de nmap para ver los puertos abiertos de la máquina:

-p-: Englobar el rango total de puertos (1-65535).

--open: Mostrar solo los puertos que estén abiertos.

--min-rate 5000: Enviar paquetes no mas lento que 5000 paquetes por segundo.

-sS: Indicamos el modo de escaneo TCP SYN scan.

-Pn: No aplicar descubrimiento de hosts.

-n: No aplicar resolución DNS.

-oG: Exportar el escaneo en un formato específico.

veremos 3 puertos abiertos, por lo que realizaremos un escaneo mas profundo pero solo a esos:

-sC: Aplicar los scripts básicos de reconocimiento

-sV: Identificar los servicios corren en los puertos y

-oN: Exportarlo tal cual como se muestra por consola.

Tenemos algunas cosas interesantes:

  • nmap encontró un .git en la web.

  • Hay un servicio desconocido que nos pide contraseña.

Como no tenemos la contraseña para el puerto 65453 pasaremos a la web.

Puerto 80

Comenzaremos usando git-dumper para descargar el repositorio .git de la web:

una vez termine, veremos una carpeta llamada 'web' que contiene el index.php de la web, el cual si lo leemos veremos lo siguiente:

esto significa que todo lo que pasemos por el método GET usando el parámetro command_execute se ejecutaría en el sistema, pero al probarlo vemos que no funciona:

viendo esto puede que sea un commit viejo por lo que esto no nos serviría de nada.

También podremos notar que cada vez que entramos en la web el código de estado es 500:

500

esto puede significar que la web si está esperando un parámetro, pero no sabemos cual, por lo que usaremos ffuf para buscarlo:

luego de esperar a que termine, no nos reporta nada, por lo que probaremos pasar el parámetro por POST en vez de GET, pero en mi caso con ffuf no funcionó, por lo que lo hice con un script en python:

lo ejecutamos y vemos lo siguiente:

por lo que ya sabemos cual es el parámetro y vemos que nos permite leer archivos en vez de ejecutar comandos.

Si revisamos el código del index.php veremos lo siguiente:

como vemos nos muestra el contenido de los archivos con la función file_get_contents(), por lo que no podremos usar scripts como php_filter_chain_generator para ejecutar comandos ya que no lo hace con include() y por lo tanto no servirá de nada. Pero lo que si podemos hacer es ver que procesos hay en la máquina, para esto también crearemos un script en python:

lo ejecutamos y vemos los siguientes proceso:

de todos estos el único que nos interesa es el de xinetd, ya que nos da una pista. Pero primero:

¿Que es xinetd?

xinetd es un demonio de Internet (daemon) en sistemas Unix/Linux que funciona como un servidor de "supervisión" para gestionar otros servicios de red.

¿Cual es su función principal?

La función principal de xinetd es escuchar puertos de red en espera de conexiones entrantes, y cuando una conexión es solicitada en un puerto determinado, redirige la solicitud al servicio adecuado para que lo atienda.

Esto significa que xinetd puede ser el servicio que escucha por el puerto 65453 pero lo redirige a otro, que no necesariamente es un servicio, si no un binario tal como puede ser bash, ls o uno personalizado. Sabiendo esto ¿Que podríamos hacer?; con esta información podríamos revisar todos los servicios gestionados por xinetd, los cuales son un simple archivo de configuración individual en /etc/xinetd.d/, por lo que haremos nuevamente un script en python que lo haga:

lo ejecutamos y nos muestra lo siguiente:

el último servicio es el único que nos interesa, ya que este nos muestra cual es el binario que se ejecuta. Ahora guardaremos el binario para revisarlo:

una vez guardado borraremos el 'Welcome' que queda en el comienzo del archivo, para esto se puede usar nano,nvim o cualquier editor de texto.

Una vez todo listo, ejecutamos file manager y vemos lo siguiente:

esto nos dice que es un binario de 64bits. Si lo ejecutamos veremos que también nos pide una contraseña, por lo que podemos averiguarla usando ltrace:

como podemos ver, la contraseña que espera es 'S3cr3tP@ssw0rd123', por lo que podemos intentar ponerla:

como vemos funciona y podemos leer archivos del sistema, pero esto no nos sirve ya que lo podíamos hacer antes. Podemos ver la segunda opción:

esta opción nos pide un input, podemos intentar enviar mucho contenido para ver si se acontece un buffer overflow:

efectivamente, estamos frente un buffer overflow.

Intrusión

Buffer Overflow - ROP

Si revisamos las protecciones del binario veremos que solo tiene activado NX:

Protecciones

Esto significa que el stack no es ejecutable, sin embargo las direcciones de la memoria no son aleatorias, no tiene canarios ni RELRO, por lo que nos quedan dos tipos posibles de buffer overflow por hacer:

  • ROP

  • Ret2libc

En este caso nos conviene realizar un Bof de tipo ROP ya que es mas sencillo. Para empezar podríamos hacer la base de nuestro exploit:

por ahora solo nos faltaría buscar:

Obtener el offset

Para obtener el offset usaremos la herramienta pattern_create.rb y pattern_offset.rb de metasploit. Primero generaremos un pattern y lo pasaremos por gdb:

copiamos el output y ejecutamos gdb:

En mi caso tengo pwndbg

Ahora lo ejecutamos, y al llegar a la parte vulnerable enviamos el pattern:

pattern

ahora usaremos pattern_offset.rb para obtener el offset:

por lo que ya tenemos el offset y podemos actualizar el exploit:

ahora vamos a obtener la direcciónn de system.

Dirección system

ya tenemos la dirección: 0x401050 y podemos actualizar el exploit:

ahora debemos buscar una función o gadget que nos ayude.

Gadgets

Usaremos ghidra para buscarlos.

En la función LTe ya podemos ver algo útil:

LTe

vemos 2 instrucciones interesantes, la cuales son

  • MOV RDI,RSP

  • JMP R13

Esto nos interesa ya que la primer instrucción copia el contenido de RSP (el tope de la pila) al registro RDI, esto es interesante porque al llamar a system busca el primer valor que se encuentre en el registro rdi, rsi, rcx, rdx ,r9..., por lo que cuando lleguemos al tope de la pila podremos meter nuestra cadena '/bin/sh' en el registro rdi el cual posteriormente usará system. Luego vemos JMP R13, lo cual nos sirve para poder llamar a system ya que la función LTe salta a r13 en el final, podemos buscar un gadget como pop r13 para cargar la dirección de system en el r13 y cuando la función LTe sea llamada, ejecutará /bin/sh correctamente.

Extraer la dirección de pop r13 y la función LTe

Para obtener la dirección de la función es tan simple como hacerlo con objdump:

por lo tanto la dirección sería 0x4011c6.

Para obtener la dirección del gadget podemos usar ropper:

pop r13

y ya tenemos la dirección: 0x4011d7. Ahora podemos terminar el exploit:

lo ejecutamos y vemos lo siguiente:

pwned

como vemos, hemos logrado obtener una shell a través del buffer overflow. Ahora solo nos queda hacer que el exploit no se ejecute en local y se conecte al puerto remoto:

y al ejecutarlo estaremos dentro:

Intrusion

Escalada de privilegios

Ahora que estamos dentro, somos el usuario maci, pero nos enviaremos una shell para tener una shell totalmente interactiva:

escuchamos con netcat:

y al enviar la shell podremos ver la flag de user:

User.txt

Si ejecutamos sudo -l veremos lo siguiente:

sudo

podemos ejecutar un binario llamado name como el usuario dk, vamos a revisarlo.

name

nuevamente, tenemos un binario vulnerable a buffer overflow.

Buffer overflow - Function call

Comenzaremos pasandolo a nuestra máquina local. Si ejecutamos file y checksec veremos que es un binario de 64 bits con las mismas protecciones que el anterior. Pero cuando lo revisamos con gdb, veremos una función llamada future_function, esta función no se llama nunca en el binario, pero si ejecutamos strings ./name veremos lo siguiente:

lo que significa que esa función probablemente ejecute /bin/bash. Para llamar a la función es mucho mas simple:

la diferencia es que no tenemos pwntools para facilitarnos todo.

Una vez ejecutado veremos lo siguiente:

DK

nuevamente nos enviaremos una shell.

Dk

Si ejecutamos sudo -l veremos que podemos ejecutar exim4 como root. Luego de leer el manual, podemos ver una forma de ejecutar comandos:

por lo que crearemos un script en /tmp que nos deje ejecutar cualquier comando como root:

le damos permisos de ejecución:

y lo ejecutamos:

luego podremos escalar a root ejecutando sudo su

Root

root

Última actualización