إرسال السجلات والتنبيهات وبيانات القياس عن بُعد عبر صمام ثنائي البيانات

اكتشف كيف
نستخدمُ الذكاء الاصطناعي في ترجمات الموقع، ومع أننا نسعى جاهدين لبلوغ الدقة قد لا تكون هذه الترجمات دقيقةً بنسبة 100% دائمًا. تفهّمك لهذا الأمر هو موضع تقدير لدينا.

React2Shell (CVE-2025-55182): ثغرة خطيرة تسمح بتنفيذ التعليمات البرمجية عن بُعد في Server React

By لوك نجوين، قائد فريق اختبار الاختراق
شارك هذا المنشور

CVE-2025-55182 هي ثغرة أمنية خطيرة تسمح بتنفيذ التعليمات البرمجية عن بُعد قبل المصادقة في Server React، وتحمل درجة CVSS تبلغ 10.0 - وهي أعلى درجة خطورة ممكنة. كجزء من برنامج زمالةOPSWAT ، أجرى زملاؤنا تحليلاً تقنياً شاملاً لهذه الثغرة الأمنية، حيث فحصوا السبب الجذري لها في بروتوكول إزالة التسلسل React Flight، وسلسلة الاستغلال الكاملة، وتأثيرها الواسع النطاق عبر النظام البيئي للويب الحديث. يعرض هذا المدونة النتائج التي توصلنا إليها إلى جانب إرشادات قابلة للتنفيذ للمتخصصين في مجال الأمن السيبراني.

أصبحت React واحدة من أكثر مكتبات الواجهة الأمامية انتشارًا في العالم، حيث تُستخدم في نسبة كبيرة من mobile الويب mobile الحديثة. تصنف استطلاعات المطورين التي تجريها Stack Overflow React باستمرار ضمن أفضل أطر عمل الويب، حيث يتجاوز معدل استخدامها 40% من المطورين المحترفين على مستوى العالم. وبالتوازي مع هذا النمو، قدم فريق React Server React (RSC) كميزة أساسية في React 19 - وهو تحول جذري ينقل منطق العرض من العميل إلى الخادم، مما يتيح أداءً محسّنًا وتكاملًا أوثق بين كود جانب الخادم وكود جانب العميل.

ومع ذلك، أدى هذا التطور المعماري إلى ظهور نقطة ضعف جديدة وخطيرة. في 29 نوفمبر 2025، أبلغ الباحث الأمني لاكلان ديفيدسون برنامج مكافآت الأخطاء (Bug Bounty) التابع لشركة ميتا عن ثغرة أمنية في منطق إزالة التسلسل من جانب الخادم في React. وقد تم الكشف عن هذه الثغرة علنًا في 3 ديسمبر 2025 تحت الرمز CVE-2025-55182، وهي تتيح تنفيذ تعليمات برمجية عن بُعد دون مصادقة من خلال طلب HTTP واحد مُصمم خصيصًا. تم تصنيف هذه الثغرة الأمنية على أنها CWE-502 (إلغاء تسلسل البيانات غير الموثوق بها)، ولا تتطلب أي مصادقة أو تفاعل من المستخدم أو تكوين خاص للتطبيق - حيث يمكن استغلال النشر الافتراضي لـ create-next-app المصمم للإنتاج على الفور.

الشكل 1: CVE-2025-55182 (المصدر: NVD)

كان التأثير فوريًا وخطيرًا. ففي غضون 48 ساعة من الإعلان عن الثغرة، لوحظت حملات استغلال متعددة في بيئة حقيقية. ووفقًا لمؤسسة Shadowserver، تم تحديد أكثر من 77,000 عنوان IP عام على أنه معرض للخطر. سجلت أجهزة القياس عن بُعد التابعة لـ Cloudflare أكثر من 582 مليون محاولة استغلال في الأسبوع الذي أعقب الكشف عن الثغرة، حيث بلغ متوسط كثافة الهجمات أكثر من 3,500 نظام منع التطفل فريد نظام منع التطفل الساعة وبلغت ذروتها عند 16,585 نظام منع التطفل متزامنة. أفادت Wiz Research أن 39% من البيئات السحابية تحتوي على حالات عرضة للخطر. أضافت وكالة الأمن السيبراني والبنية التحتية (CISA) هذه الثغرة الأمنية إلى قائمة الثغرات الأمنية المعروفة التي تم استغلالها (KEV) في 5 ديسمبر 2025.

تحركت الجهات التهديدية بسرعة وتنوع ملحوظين. وقد وثقت شركة Trend Micro حملات متعددة — بما في ذلك حملات شبكات الروبوتات "emerald" و"nuts" — التي استخدمت إشارات Cobalt Strike، وزرعات Sliver، ووكيل المراقبة Nezha، وأنفاق Fast Reverse Proxy (FRP)، وحمولة جديدة باسم "Secret-Hunter" تستغل أدوات مفتوحة المصدر لجمع بيانات الاعتماد أدوات TruffleHog وGitleaks. حددت Threat Intelligence Google Threat Intelligence مجموعات تهديدات متميزة مرتبطة بالصين (UNC6600، UNC6586، UNC6588، UNC6603) تستخدم أدوات متخصصة - بما في ذلك أداة إنشاء الأنفاق MINOCAT، وأداة التنزيل SNOWLIGHT، والباب الخلفي COMPOOD، والباب الخلفي HISONIC - إلى جانب جهات فاعلة مرتبطة بإيران ومجموعات ذات دوافع مالية تقوم بحملات تعدين العملات المشفرة. وثقت AWS مجموعات مرتبطة بالصين وهي تجرب رموز الاستغلال منذ 4 ديسمبر، قبل أن يصبح رمز إثبات المفهوم الكامل متاحًا للجمهور.

نبذة عن Server React

React هي مكتبة JavaScript مخصصة لإنشاء واجهات المستخدم، وتقوم بصيانتها شركة Meta ومجتمع مفتوح المصدر واسع النطاق. تمثل Server React (RSC)، التي تم تقديمها مع React 19، تحولًا جوهريًا في كيفية تعامل تطبيقات React مع العرض. على عكس مكونات العميل التقليدية التي يتم تنفيذها بالكامل في المتصفح، يتم تنفيذ مكونات الخادم على الخادم، مما ينتج عنه تمثيل متسلسل لواجهة المستخدم يتم بثه إلى العميل. يقلل هذا التصميم من كمية JavaScript التي يتم إرسالها إلى المتصفح، ويحسن مقاييس وقت التفاعل، ويتيح الوصول المباشر إلى موارد جانب الخادم مثل قواعد البيانات وأنظمة الملفات.

الشكل 2: Server React (RSC)

يعتمد RSC على بروتوكول تسلسل مخصص يُسمى «Flight» لترميز البيانات ونقلها بين العميل والخادم. عندما يستدعي العميل Server (المعروفة سابقًا باسم Server )، يقوم المتصفح بتجميع معلمات الوظيفة في طلب HTTP منظم باستخدام تنسيق Flight. يقوم الخادم بإلغاء تسلسل هذه الحمولة، وتنفيذ الوظيفة المطلوبة، وإرسال النتيجة إلى العميل. هذا الترابط الوثيق بين العميل والخادم (على الرغم من أناقة تصميمه) يعني أن أي خلل في منطق إلغاء التسلسل يمكن أن يكون له عواقب فورية وكارثية، كما يوضح CVE-2025-55182.

لا تؤثر هذه الثغرة الأمنية على React فحسب، بل على النظام البيئي بأكمله للإطارات المبنية عليها. تتأثر كل من Next.js (التي تلقت تنبيهًا منفصلاً، CVE-2025-66478، تم رفضه لاحقًا باعتباره مكررًا)، وReact Router، وWaku، ومكوّن RSC الإضافي لـ Parcel، ومكوّن RSC الإضافي لـ Vite، وRedwoodSDK. حتى التطبيقات التي لا تحدد Server بشكل صريح قد تكون عرضة للخطر إذا تم تمكين دعم RSC في إطار العمل.

الخلفية التقنية

قبل دراسة الثغرة الأمنية، هناك ثلاثة مفاهيم أساسية تشكل أساس سلسلة الاستغلال: سلوك الأمر «await» في JavaScript مع الكائنات القابلة للتنفيذ باستخدام «then»، وعبور سلسلة النماذج الأولية، ونموذج البيانات القائم على «chunk» في بروتوكول React Flight.

كائنات await و Thenable في JavaScript

يعمل عامل "await" على إيقاف تنفيذ الدالة غير المتزامنة مؤقتًا حتى يتم حل التعبير المنتظر. وعندما يصادف عامل "await" وعدًا أصليًا (Promise)، فإنه ينتظر إتمامه ويعيد القيمة التي تم الوفاء بها. ومع ذلك، لا يشترط عامل "await" وجود وعد أصلي؛ فأي كائن يحتوي على طريقة .then() ، والمعروف باسم "thenable"، يُعامل على أنه بنية شبيهة بالوعد.

عندما تصادف كلمة `await` كائنًا قابلًا للتنفيذ (`thenable`)، فإنها تستدعي طريقة `.then()` الخاصة بالكائن، مع تمرير دالتي الاستدعاء `resolve` و`reject` اللتين يوفرهما النظام. وتصبح القيمة التي يتم تمريرها إلى `resolve` هي نتيجة تعبير `await`. والأهم من ذلك، إذا كانت القيمة التي تم حلها هي نفسها thenable، يتم استدعاء طريقة .then() لهذا الكائن المتداخل بشكل متكرر حتى الوصول إلى قيمة أولية أو Promise مستقرة. هذا السلوك المتكرر لحل المشكلة هو أمر أساسي لاستغلال CVE-2025-55182.

تجول سلسلة النموذج الأولي

يحتفظ كل كائن في JavaScript برابط داخلي إلى نموذجه الأولي (prototype)، والذي يمكن الوصول إليه عبر الخاصية __proto__. وعند الوصول إلى خاصية ما في كائن ما، يقوم محرك JavaScript أولاً بفحص الخصائص الموجودة في الكائن نفسه. وإذا لم يتم العثور على الخاصية، يتتبع المحرك سلسلة النماذج الأولية — متجولاً عبر كل رابط __proto__ — حتى يتم العثور على الخاصية أو تنتهي السلسلة عند قيمة undefined.

يمكن للمهاجم استغلال آلية التوريث هذه للوصول إلى خصائص تتجاوز النطاق المقصود للكائن. ومن خلال تضمين __proto__ في مسارات الوصول إلى الخصائص، يمكن للمهاجم الوصول إلى الطرق الداخلية ومُنشِئات الكائنات التي لم يقصد التطبيق أبدًا الكشف عنها. وفي لغة جافا سكريبت، يُسفر التعبير obj.__proto__.constructor.constructor عن مُنشِئ Function العالمي، والذي يمكنه إنشاء وتنفيذ دوال عشوائية من مدخلات سلسلة نصية.

بروتوكول React Flight ونموذج البيانات القائم على الأجزاء

When a client invokes a Server Function, the browser sends an HTTP POST request with a multipart/form-data body. Each form field contains a numbered “chunk” of serialized data. The Flight protocol uses special string prefixes to encode data types: $<id> references the resolved value of another chunk, $@<id> references the raw chunk object itself, $W<id> represents a Set, $K<id> represents FormData, and $B<id> triggers the blob handler.

لنفترض وجود Server مُعرَّفة على النحو التالي:

الشكل 3: مثال على Server

يحتوي طلب HTTP المقابل على حقول نموذج متعددة، يتألف كل منها من مفتاح وقيمة: يحتوي الحقل 0 على مصفوفة المعلمات التي تتضمن مراجع مثل "$W1" و "$K2"، بينما تحتوي الحقول 1 و2_* على البيانات التي تشير إليها تلك المراجع. ويقوم الخادم بمعالجة كل حقل فور وصوله، مع تخزين النتائج المؤقتة في كائنات تُسمى "chunks".

الشكل 4: طلب HTTP متعدد الأجزاء/بيانات النموذج المقابل الذي يتم إنشاؤه عند استدعاء Server في المثال

القطعة (chunk) هي كائن قابل للتنفيذ (thenable) يحتوي على أربع خصائص رئيسية: status (حالة التحليل)، value (البيانات المخزنة)، reason (معلومات الخطأ)، و_response (إشارة رجعية إلى كائن الاستجابة الأصلي). عندما يواجه الخادم await chunk، يتم استدعاء طريقة .then() الخاصة بالقطعة. إذا كانت حالة القطعة هي INITIALIZED، فإن استدعاء الحل (resolve callback) يتلقى chunk.value. إذا كانت الحالة هي PENDING أو BLOCKED أو CYCLIC، يتم وضع استدعاءات الحل في قائمة الانتظار لتنفيذها لاحقًا.

الشكل 5: حالة كائن "chunk" أثناء عملية إزالة التسلسل

يمثل "Chunk 0" عادةً مصفوفة المعلمات الخاصة Server التي تم استدعاؤها. وبعد استلام جميع حقول النموذج وحل جميع الإشارات الداخلية، تحتوي "chunk_0.value" على مصفوفة المعلمات المجمعة بالكامل، والتي يتم تمريرها بعد ذلك إلى الوظيفة المستهدفة.

معالجة الطلبات من البداية إلى النهاية (Next.js → إزالة التسلسل في React Flight)

فيما يلي شرح لكيفية معالجة Next.js لطلب Server الوارد في الظروف العادية، بدءًا من طبقة HTTP وصولاً إلى محرك إزالة التسلسل React Flight.

الشكل 6: نظرة عامة على معالجة الطلبات في Server في Next.js

الدالة handleAction() - Next.js

عند استدعاء Server يدخل الطلب إلى وظيفة handleAction. تقوم هذه الوظيفة بالتحقق من صحة البيانات الوصفية، وفحص الرؤوس ورموز CSRF، والتأكد من أن الطلب يمثل عملية جلب صالحة. ثم يتم إنشاء دفق يسمى busboyStream لتحليل نص النموذج متعدد الأجزاء. تربط وظيفة decodeReplyFromBusboy بواعث الأحداث بهذا الدفق، مما يؤدي إلى تشغيل وظائف معالج إزالة التسلسل ServerReact عند استلام البيانات الأولية. قيمة الإرجاع لـ decodeReplyFromBusboy هي chunk_0؛ يقوم عامل await بحلها وتمرير قيمتها المجمعة إلى Server التي تم استدعاؤها.

الشكل 7: دالة handleAction

تُرجع الدالة getChunk الجزء المطابق لمعرف معين. وإذا لم يكن هذا الجزء موجودًا بعد، فإنها تنشئ إما كائن ResolvedModelChunk (إذا كانت البيانات موجودة بالفعل في response._formData) أو كائن PendingChunk (إذا لم تصل أي بيانات لهذا المعرف بعد).

الشكل 8: دالة getChunk

عندما تُرجع دالة decodeReplyFromBusboy القيمة chunk_0، تظل المقطوعة في حالة PENDING. ويقوم عامل await باستدعاء chunk_0.then() ويخزن مؤقتًا دالتي الاستدعاء resolve و reject في chunk_0.value و chunk_0.reason. وتُعاد تنشيط دالتي الاستدعاء هاتين بواسطة دالة wakeChunk بمجرد اكتمال تحديد المرجع.

الشكل 9: دالة wakeChunk

عملية إزالة التسلسل - Server React

عندما يتلقى busboyStream حقل بيانات خام كامل، فإنه يُشغّل مُصدر الحدث "field"، ويستدعي الدالة resolveField، ويبدأ عملية إزالة التسلسل — أي تحويل بيانات النموذج الخام إلى كائنات JavaScript مكتملة البناء. وتُحكم الدوال التالية هذه العملية.

resolveField(الاستجابة، المفتاح، القيمة)

الشكل 10: دالة resolveField

يتم إضافة المفتاح والقيمة إلى response._formData. ثم تسترد الدالة الجزء الذي يتوافق مع المعرف المطابق للمفتاح. إذا كان هذا الجزء موجودًا بالفعل، يتم استدعاء resolveModelChunk لإعادة بنائه. ويعد هذا الحل المؤجل ضروريًا لأن القيمة قد تحتوي على إحالات إلى حقول لم تصل بياناتها الأولية بعد؛ وفي هذه الحالة، Server React Server PendingChunk مع دالات استدعاء مخصصة للقبول والرفض لمعالجة تلك الإحالات لاحقًا.

resolveModelChunk(chunk, value, id)

الشكل 11. دالة resolveModelchunk

تقوم دالة `resolveModelChunk` بإنشاء كائن `ResolvedModelChunk` بحالة `RESOLVED_MODEL` وتقوم بإدخال البيانات الأولية إليه. ثم تعيد بناء المقطع عبر دالة `initializeModelChunk` وتستدعي دالة `wakeChunk` لتشغيل أي دالات استدعاء (callbacks) من نوع `resolve` و`reject` الموجودة في قائمة الانتظار، وبذلك تكتمل عملية تحديد الكائن أو المرجع.

تهيئة جزء النموذج (chunk)

الشكل 12: دالة initializeModelChunk

تقوم وظيفة `initializeModelChunk` بتحويل حالة المقطع إلى CYCLIC — مما يشير إلى أن عملية تحليل المراجع جارية — وتبدأ عملية إزالة التسلسل. وتقوم بإنشاء كائن JavaScript أولي من `chunk.value` باستخدام `JSON.parse`، ثم تمرر هذا الكائن إلى وظيفة `reviveModel`.

reviveModel(الاستجابة، الكائن الأبوي، مفتاح الكائن الأبوي، القيمة، المرجع)

الشكل 13: دالة reviveModel

تقوم وظيفة reviveModel بمعالجة كل مكون داخل الكائن الذي تم تحليله بشكل متكرر. وعندما تصادف قيمة نصية، فإنها تستدعي وظيفة parseModelString لمعالجتها.

parseModelString(الاستجابة، الكائن، المفتاح، القيمة، المرجع)

الشكل 14. دالة parseModelString

تقوم الدالة `parseModelString` بتحديد معالج الأنواع المختلفة بناءً على بادئة السلسلة. بالنسبة للمراجع التي تبدأ بعلامة $، يتم استدعاء الدالة `getOutlinedModel` لحل المراجع المشتركة بين المقاطع.

getOutlinedModel(الاستجابة، المرجع، الكائن الأصلي، المفتاح، الخريطة)

الشكل 15: دالة getOutlinedModel

تقوم وظيفة getOutlinedModel بتقسيم المرجع عند الفاصل":" لتشكيل مسار الوصول إلى الخاصية، ثم تتتبع هذا المسار في كائن المقطع المستهدف لإرجاع القيمة المشار إليها. وكما هو موضح بالتفصيل في "تحليل الثغرة الأمنية" أدناه، فإن عدم وجود عملية تحقق من صحة أسماء الخصائص هذه هو بالضبط المكان الذي توجد فيه الثغرة الأمنية.

تحليل نقاط الضعف

السبب الجذري

CVE-2025-55182 originates from insufficient input validation in the getOutlinedModel() function within React’s server-side Flight reply handler (ReactFlightReplyServer.js). When a chunk reference includes a property path - such as $<id>:<prop1>:<prop2> - the function resolves it by traversing the specified properties on the target chunk object, computing the result as chunk[prop1][prop2].

الشكل 16: عدم كفاية التحقق من صحة المدخلات في دالة getOutlinedModel()

يكمن الخلل الخطير في أن أسماء الخصائص هذه لا تخضع أبدًا للتحقق من صحتها. لا يتحقق الخادم مما إذا كانت الخصائص المطلوبة هي خصائص خاصة بالكائن أم خصائص نموذجية موروثة. وبالتالي، يمكن للمهاجم تضمين __proto__ في مسار الخاصية لاجتياز سلسلة النماذج الأولية والوصول إلى الطرق الداخلية التي لا ينبغي أبدًا أن تكون متاحة من خلال المدخلات التي يتحكم فيها المستخدم. على سبيل المثال، يتم تحويل المرجع $1:__proto__:then إلى Chunk.prototype.then - وهي دالة يمكن للمهاجم بعد ذلك استدعاؤها باستخدام معلمات يمكنه التحكم فيها.

الشكل 17: اختراق النموذج الأولي عبر مدخلات ضارة

الرمز الضعيف

تستغل سلسلة الاستغلال مسارين مختلفين للرمز في منطق إزالة التسلسل في React Flight.

الأول هو Chunk.prototype.then، الذي يحدد كيفية تصرف المجموعات (chunks) باعتبارها كائنات قابلة للتنفيذ باستخدام then (thenables). وعندما يتم تطبيق الأمر await على مجموعة في حالة INITIALIZED، يتم استدعاء resolve(chunk.value). وإذا كانت chunk.value نفسها كائنًا قابلاً للتنفيذ باستخدام then (كائن يحتوي على طريقة .then() )، فإن عامل await يستدعي chunk.value.then() بشكل متكرر. وهذا الحل المتكرر هو الآلية التي يستخدمها المهاجم لإعادة توجيه التنفيذ إلى دالة عشوائية.

والثاني هو معالج البادئة $B (blob) داخل الدالة parseModelString():

الشكل 18: $B (blob) في دالة parseModelString

في الحالة $B، تستدعي الدالة response._formData.get(response._prefix + id). وتعد كل من _formData.get و_prefix خاصيتين لكائن _response المخزّن داخل المقطع. ومن خلال التحكم في هاتين الخاصيتين عن طريق تتبع سلسلة النماذج الأولية، يمكن للمهاجم إعادة توجيه هذا الاستدعاء لاستدعاء مُنشئ الدالة العالمية (Function) مع إدخال رمز تعسفي كحجة له.

الاستغلال

Through prototype chain traversal, an attacker reaches the global Function constructor via the path <any_object>.constructor.constructor. Because Chunk.prototype.then is a function, the path $1:constructor:constructor resolves to the global Function constructor, which accepts a string and returns a callable function containing that code.

الشكل 19: مُنشئ الدالة العالمية

ولإثبات التأثير المحتمل في الواقع العملي، قام زملاؤنا بتصميم حمولة إثبات المفهوم تتماشى مع التحليلات الموثقة بشكل مستقل من قبل العديد من فرق البحث الأمني. ويعمل هذا الاستغلال على مرحلتين:

المرحلة الأولى - إنشاء الجزء الوهمي:

The object delivered in field 0 acts as a fake chunk. Its then property is set to Chunk.prototype.then via the reference path $1:__proto__:then, allowing the Flight deserialization engine to invoke prototype-level behavior on this attacker-constructed object. The _response._formData.get property is pointed at the global Function constructor via $1:constructor:constructor, and _response._prefix is set to the malicious JavaScript code. The value field contains the string {"then": "$B0"}, instructing the blob handler to invoke itself on the same chunk when resolved. The status field is set to resolved_model so that initializeModelChunk is triggered when .then() is called, causing value to be parsed and the blob handler to fire.

نظرًا لأن الحقل 1 لم يتم استلامه بعد في هذه المرحلة، يقوم Server React Server بإنشاء دالات استدعاء "resolve" و"reject" للتعامل مع المرجع المعلق.

المرحلة الثانية - حل المشكلة:

بمجرد تسليم الحقل 1 - الذي يحتوي على "$@0"، وهو مرجع أولي إلى المقطع 0 - يتم تحليل المقطع المعلق ويشير مباشرةً إلى المقطع الوهمي. يؤدي هذا إلى تشغيل wakeChunk، الذي يعالج عمليات الاستدعاء المرتبطة الموجودة في قائمة الانتظار ويبدأ في اجتياز سلسلة النماذج الأولية أثناء تحليل المرجع. بمجرد حل المقطع المزيف بالكامل، يتم استدعاء wakeChunk مرة أخرى. نظرًا لأن استدعاء الحل للمقطع المزيف هو وظيفة الحل الضمنية في Node.js، فإنه يستدعي طريقة .then() الخاصة بالمقطع ويحل قيمته - مما يؤدي في النهاية إلى إنشاء وتنفيذ الشفرة الخبيثة التي تم حقنها عبر منشئ Function.

لا يتطلب الاستغلال الكامل سوى طلب HTTP واحد:

الشكل 20. طلب ضار

Replacing {{COMMAND}} with any JavaScript code executes it on the server. The reason: -1 field prevents a toString() error during processing. The Next-Action header may contain any arbitrary value - even x - because the vulnerable deserialization occurs before the server validates the requested Server Function. This is what makes the vulnerability pre-authentication: the payload is processed during the deserialization phase, before any application-level authentication or authorization logic is reached.

في حالة نجاح الاستغلال، يحصل المهاجم على سياق تنفيذ Node.js الكامل على الخادم، بما في ذلك الوصول إلى `child_process` لتنفيذ أوامر شل، ومتغيرات البيئة التي تحتوي على بيانات اعتماد قاعدة البيانات API ، ونظام الملفات المحلي، ونقاط نهاية البيانات الوصفية السحابية التي تتيح التنقل الأفقي.

إثبات المفهوم

تمكن زملاؤنا من إعادة إنتاج هذه الثغرة الأمنية في بيئة مختبرية خاضعة للرقابة، وذلك باستخدام تطبيق Next.js قياسي تم إنشاؤه بواسطة الأداة create-next-app وتجهيزه للإنتاج — دون إجراء أي تعديلات على الإعدادات الافتراضية. وأثبتت عملية إعادة الإنتاج أن حمولة الاستغلال ذات الطلب الواحد الموصوفة أعلاه تتيح تنفيذ التعليمات البرمجية عن بُعد بشكل موثوق.

الشكل 21. تطبيق ويب Next.js معرض للخطر
الشكل 22. المهاجم يخترق خادم Next.js المعرض للخطر

أظهرت التجربة المُراقبة أن المهاجم الذي يتمتع بوصول شبكي إلى خادم Next.js معرض للخطر يمكنه تنفيذ تعليمات برمجية Node.js تعسفية — بما في ذلك إنشاء قذيفة عكسية عبر child_process.exec()، وقراءة متغيرات البيئة، والوصول إلى نظام الملفات المحلي — دون الحاجة إلى تقديم أي بيانات اعتماد أو تشغيل أي عمليات تحقق من المصادقة على مستوى التطبيق. وتؤكد القيمة التعسفية المقبولة لرأس Next-Action طبيعة الثغرة قبل المصادقة: حيث يقوم الخادم بمعالجة الحمولة وإلغاء تسلسلها قبل إجراء أي بحث عن الإجراء أو فحص للتفويض.

التخفيف

أصدر فريق React تصحيحات في 3 ديسمبر 2025 - وهو نفس اليوم الذي تم فيه الكشف عن الثغرة الأمنية للجمهور. تتوفر الإصدارات المُصححة في React 19.0.1 و19.1.2 و19.2.1. يضيف التصحيح التحقق الصارم من صحة الخصائص في getOutlinedModel() و reviveModel()، مما يمنع بشكل صريح تحليل خصائص النموذج الأولي الموروثة - بما في ذلك __proto__ و constructor و prototype - من مسارات المرجع التي يتحكم فيها المستخدم في حمولات Flight.

ينبغي على المنظمات اتخاذ الإجراءات الفورية التالية:

  1. قم بترقية حزم React إلى إصدار تم إصلاحه (19.0.1 أو 19.1.2 أو 19.2.1) عن طريق تشغيل الأمر npm install react-server-dom-webpack@latest أو react-server-dom-parcel@latest أو react-server-dom-turbopack@latest حسب الحاجة.
  2. تحديث تبعيات الأطر - أصدرت Next.js وReact Router وWaku وغيرها من الأطر المتأثرة تصحيحات مناسبة. يرجى الرجوع إلى تنبيهات فريق React للاطلاع على مسارات التحديث الخاصة بكل إصدار.
  3. لا تعتمد فقط على الإجراءات الوقائية التي يتخذها مزودو خدمات الاستضافة - ففي حين أن مزودين مثل Vercel قاموا بتطبيق قواعد مؤقتة لجدار الحماية من الهجمات الويب (WAF) عقب الكشف عن الثغرة، فإن هذه الإجراءات تعتبر حلولاً مؤقتة ولا تحل محل إصلاح الحزم الأساسية.
  4. افحص سجلات الخادم بحثًا عن طلبات POST التي تحمل رؤوس Next-Action مع نصوص multipart/form-data تحتوي على أنماط $@ أو __proto__، وراقب سجلات التطبيق بحثًا عن أي استدعاءات غير متوقعة لـ child_process أو execSync.

التخفيف من المخاطر باستخدام OPSWAT

توفر OPSWAT وهي تقنية حصرية ضمن منصة MetaDefender™، الرؤية والتحكم اللازمين للدفاع ضد الثغرات الأمنية مثل CVE-2025-55182. ونظرًا لوجود هذا الخلل في حزم npm مفتوحة المصدر (react-server-dom-webpack، وreact-server-dom-parcel، وreact-server-dom-turbopack)، يجب على المؤسسات أولاً إنشاء قائمة جرد كاملة بأماكن نشر هذه المكونات عبر بنيتها التحتية قبل أن يصبح من الممكن إجراء الإصلاح الفعال.

الشكل 23. قائمة مكونات البرمجيات (SBOM) تكتشف الثغرة الأمنية CVE-2025-55182

يقوم OPSWAT بإنشاء قائمة شاملة بجميع مكونات البرامج والمكتبات والحاويات والتبعيات قيد الاستخدام. وعند فحص التطبيقات أو صور الحاويات التي تتضمن حزم React المعرضة للخطر، يقوم النظام تلقائيًا بتصنيف الثغرة CVE-2025-55182 على أنها "حرجة" ويقدم إرشادات بشأن الإصدارات المُصلحة المتاحة، مما يمكّن فرق الأمن من تحديد الأولويات واتخاذ الإجراءات التصحيحية قبل وقوع أي استغلال.

يتوفر OPSWAT في كل من MetaDefender - لفحص التطبيقات الفردية وصور الحاويات - MetaDefender Software Chain™ - لتوفير رؤية شاملة على مستوى مسار العمل طوال دورة حياة التطوير بأكملها. ويُتيح هذان المنتجان معًا لفرق الأمن ما يلي:

  • تحديد المكونات المعرضة للخطر بسرعة - تحديد التطبيقات والحاويات التي تتضمن حزم react-server-dom-* المتأثرة في الإصدارات المعرضة للخطر على الفور، لضمان عدم إغفال أي عملية نشر.
  • ضمان إجراء التصحيحات بشكل استباقي - مراقبة التبعيات مفتوحة المصدر باستمرار للكشف عن الحزم القديمة أو غير الآمنة فور نشر التنبيهات الجديدة، مما يقلل من فترة التعرض للمخاطر.
  • الحفاظ على الامتثال والشفافية في سلسلة التوريد - تلبية المتطلبات التنظيمية من خلال الاحتفاظ بسجل قابل للتدقيق لجميع مكونات البرامج ونقاط الضعف المعروفة فيها.

إن السرعة والنطاق اللذين اتسم بهما استغلال الثغرة الأمنية CVE-2025-55182 - حيث سُجلت أكثر من 582 مليون محاولة في الأسبوع الأول وحده - يؤكدان أن إصلاح الثغرات بشكل رد الفعل لم يعد كافياً. إن معرفة ما تمتلكه، وأين يعمل، ومتى يصبح عرضة للخطر، هي أساس الدفاع الاستباقي. وتبدأ هذه الرؤية بـ SBOM.

مراجع

ابق على اطلاع دائم OPSWAT!

اشترك اليوم لتلقي آخر تحديثات الشركة, والقصص ومعلومات عن الفعاليات والمزيد.