backfire (HTB)
Does C2 even secure ??
Introduction.
Hello everyone today we are back on new machine Backfire season machine on HTB let's get right into it.
Enumeration.
Port scanning
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 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 ttl 63 nginx 1.22.1
|_ssl-date: TLS randomness does not represent time
|_http-title: 404 Not Found
| ssl-cert: Subject: commonName=127.0.0.1/organizationName=SYNERGY/stateOrProvinceName=California/countryName=US/streetAddress=/localityName=Los Angeles/postalCode=7072
| Subject Alternative Name: IP Address:127.0.0.1
| Issuer: commonName=127.0.0.1/organizationName=SYNERGY/stateOrProvinceName=California/countryName=US/streetAddress=/localityName=Los Angeles/postalCode=7072
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-04T02:56:35
| Not valid after: 2027-06-04T02:56:35
| MD5: 825e:069a:f26f:23b8:581e:b758:e183:45b0
| SHA-1: 0584:d0ed:4d19:5049:9c58:b892:2a8b:b89a:62c3:07f2
| -----BEGIN CERTIFICATE-----
| MIID7DCCAtSgAwIBAgIQejL515JPEfZZ+s+iRljFBzANBgkqhkiG9w0BAQsFADB4
| MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxMLTG9z
| IEFuZ2VsZXMxCTAHBgNVBAkTADENMAsGA1UEERMENzA3MjEQMA4GA1UEChMHU1lO
| RVJHWTESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTI0MDYwNDAyNTYzNVoXDTI3MDYw
| NDAyNTYzNVoweDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDAS
| BgNVBAcTC0xvcyBBbmdlbGVzMQkwBwYDVQQJEwAxDTALBgNVBBETBDcwNzIxEDAO
| BgNVBAoTB1NZTkVSR1kxEjAQBgNVBAMTCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcN
| AQEBBQADggEPADCCAQoCggEBAJRUr26zDQeev0P3+gdZu2TEd7LgDjtJNS03jpBD
| ANBHb2Qcrg3m1n/e/SZUHULBNfyZaMcJPGXnHGLCEAo9c0L0oONZkKBukEZnXy25
| Du+oURjxAYDfOpz7P5hsbvYC3J4SYj++0ROM83pkeTumR7lll4b81Bb+33009cio
| aas4XM1r0xC3S4opQy3WG5XBMUBSl8SvJtl+tZIznHkhfgNdyY22gkkj99+bSo7k
| 3uSWMgZhyIYtwtA7nmL+wbiExqBPG+uePnf0a3eGSJxoZGYN5zEmxQnrIMvsLf/9
| Gl6Buo+a8N9gAcpfI+iTEkolnESP78E28JwCcrJlF+XqsysCAwEAAaNyMHAwDgYD
| VR0PAQH/BAQDAgKkMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNV
| HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ0j0foTTfXanFPUaxabyepSJpG3DAPBgNV
| HREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQA0LdgMcA2F9Z9oMaARdDrB
| eiRKkF8jr4CHyPzqAZ9EokVPc+Ua+kWykGp/grEP8WIIO4RIJxjO7aZ0xRVL2Mb9
| 8e6QckMFEeakTsTmHhttIPT+e6p0r8zObCDSGJg6VyjIKx3Q9NOIffgj95SPYls8
| sk4WpfiMywLvvsoqAsdxpddglXabOLGzCWhIdPBNRK3Niz6SHgzQwAWlemZA/2Lc
| lcfHdcskVtbO5PlO+SflduSTKDKr7reCxYINwkJB04cZ+fms6F2gH1g/WUiO60Al
| C06zO0T8SYUd+CH44KfFD/QyXtNseFjrNY88cIUO5CL4SS6A7GEb+PBlkHZmjn7u
|_-----END CERTIFICATE-----
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
|_http-server-header: nginx/1.22.1
8000/tcp open http syn-ack ttl 63 nginx 1.22.1
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Index of /
|_http-server-header: nginx/1.22.1
| http-ls: Volume /
| SIZE TIME FILENAME
| 1559 17-Dec-2024 11:31 disable_tls.patch
| 875 17-Dec-2024 11:34 havoc.yaotl
|_
So as we can see we have HTTP[s] and SSH let's start with HTTP as it shows some files there.

Hmmm so we have Havoc.yaotl file and disable_tls.patch let's see what they contain.
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())
}
From this message we can understand that whom ever did this patch trying to set MR. sergej up by disabling the secure web socket in the internal network hmm.
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
}
}
And this is havoc file what is havoc ???
Havoc is a C2 server which used in the post-exploitation phase to remain persistence on network.
Looking at HTTPs.

Https Seems to does not have anything let's try to figure more into the first files we found first.
finds
after a bit of searching the HTTP does not seem to have anything other than the files and there is probably Hovac end point accessible according to what i have red about havoc frame work
while am searching i found this repo
Which explain SSRF exploit in the havoc framework so i decide to test it and it works.

So as we can see here the exploit is a bit complicated but the border line is that it create a socket through the facing interface and using proxy (I think) it redirect our traffic from to the internal machine and there fore we can access internal machine thing that's how we get connection from the target machine. To better explanation and correct info refer to the blog below from the exploit created and one of the machine creators.
But getting just SSRF would not help so much we maybe able to find another one which i have came across while am reading about this.
This exploit using some crafted request is able to execute commands on the server but there is an issue when i try to exploit it i got "Connection Refused".

So i think there is a way to combing the SSRF and this exploit the get command execution on the server. Because that SSRF exploit allow us to connect socket though the server what if we can instead of write anything into the socket we write this exploit at least this what i think.
Then i found this repo who implemented combining both exploits.
So after going through the exploits one by one we are able to get RCE on the server.


As you can see in the image above we are able to get shell access on the machine amazing foothold.
After that i created SSH key because it keep disconnecting for some reason.
First we run the following command.
Then in ilya home directory will be 2 keys
ilya -> private key
ilya.pub -> public key
then we move the public key into the authorized_keys file in .ssh folder
and we just copy and paste the private key into our machine change it premissions to
600
and use the following command to connect to ssh.
ssh -i <keyName> ilya@backfire

Shell as sergej.
so when we get access with ilya we can see a note and a script.

The python script basically create new user using the default key for JWT using the admin user and then create new user for us.
but i when we attempt to run the script it give us error.

so i decide to move the file into my machine and then using SSH i create port forwarding to port 5000 which runs the hardhat server.

here a picture for the other port which use for the web interface for hardhat C2. so i forward both.
after i did so i install the pyjwt
from pip to run the script. After running the script it will generate JWT token and will generate new user we can use that user to login via the web interface both username and password uses the same thing.

From here we click on interact will take us to this page.

we choose terminal and we can run any command as the user sergej
so we can use reverse shell and get shell as the user sergej
.
from here you can generate reverse shell.
and same steps set up listener and i created ssh connection same steps as before you can stick with the netcat connection if you want.

Shell as Root.
So once i got access to the sergej user i tried to check around few things i notice.
First i attempt to change the iptables roles allowing the C2 Hardhat server to be publicly accessible but i notice something after a while the configurations has changed to the default configurations so i used pspy64 to check the process that being executed.
Initially, I modified the iptables rules to allow the C2 Hardhat server to be publicly accessible. However, I noticed that after some time, the configurations reverted to their default settings. To investigate further, I used pspy64 to monitor the processes being executed.

and here we are we can see few noticeable things such the replacement of the passwd file and the cron jobs also we can see why the iptables precest and does not change by using the iptables-restore. the first thing i think about was to modifies the passwd.bak file which as you may guess is not possible as it only allow reading.

So after a bit of search i found this blog.
Which explain a way to override files using iptables-save which we have sudo permission on it.
with that there are to things in mind first i tryed to add entry to the passwd file as follow

But this actually does not work as we do not have permission to write to the passwd file. even via iptables-save

But wait we have another entry to the passwd file via the passwd.bak file. so i tried to add it to the passwd.bak file hoping it would copy it to the passwd file therefor i will get root access.

But unfortunately no luck i believe this is the correct way but i maybe doing something wrong so is this the only why ???.
Of course not another thing that i think about when i know we can have write access to any file is to change the permission of the sudo command for the user sergej. But how can we do that
The user sergej now have root execution on iptables
and iptables-save
with no password. And how it that basically configure via file called sudoers file.

here we can specify what access for each user using the sudo command so can we allow our user sergej to have access to everything as root with no password YES !.
First thing i added my command to the iptables-save entry

Keep in mind to prefix with '\n' and end it with '\n' to put our command in new line so it can
be parsable even if the others gives errors this still will take effect.
Then i added that and as you can see below i do not have permissions to even read the file.

using the command sudo -l
we can see our permissions.

we will have multiple errors but this is fine our command has take an effect.
with that we can do what ever we want.

conclusion.
In the end this machine was a great experience it has a good ideas too specially the rooting part was so much fun.
That's all for me thank you for reading ๐ซถ

Last updated