Next.js وثغرات الوسيط: آلية تفويض غير فعالة

كتابة: Rachid.A

ترجمة: Yewlne

01 نص الترجمة

مؤخراً، قررت مع ياسر علام الذي يحمل الاسم المستعار inzo_ التعاون لإجراء بحث. بعد مناقشة عدة أهداف محتملة، قررنا التركيز على Next.js (الذي يمتلك 130,000 نجمة على GitHub، ويُحمّل أكثر من 9.4 مليون مرة أسبوعياً). هذا إطار عمل أنا على دراية جيدة به، ولدي تجارب إبداعية رائعة معه، كما تثبت نتائج أبحاثي السابقة. وبالتالي، فإن “نحن” في هذه المقالة تشير بشكل طبيعي إلى كلينا.

Next.js هو إطار عمل JavaScript كامل الوظائف يعتمد على React، ويتميز بخصائص غنية - وهو المكان المثالي للغوص في التفاصيل. مع الإيمان والفضول والمرونة، بدأنا رحلتنا لاستكشاف الزوايا الأقل شهرة، بحثًا عن الكنوز المدفونة.

بعد فترة وجيزة، اكتشفنا مشكلة كبيرة في البرنامج الوسيط. نطاق تأثيرها واسع، وجميع الإصدارات متأثرة، ولا يتطلب استغلال هذه الثغرة أي شروط مسبقة - سنقوم قريبًا بعرض التفاصيل.

الفهرس

البرمجيات الوسيطة في Next.js

أداة التفويض: كود قديم من مستوى الكنز

ترتيب التنفيذ مع middlewareInfo.name

أداة التفويض: الأمس أصبح قصيدة، واليوم يستحق المزيد

/src دليل

أقصى عمق للتكرار

استغلال الثغرات

تجاوز التفويض/إعادة الكتابة

تجاوز CSP

تحقيق DoS من خلال تسميم الذاكرة المؤقتة (ماذا؟)

توضيح

إشعار أمان - CVE-2025-29927

إخلاء المسؤولية

خاتمة

الوسيط في Next.js

تسمح لك البرامج الوسيطة بتنفيذ الشيفرة قبل اكتمال الطلب. ثم يمكنك تعديل محتوى الاستجابة (مقتبس من وثائق Next.js) من خلال إعادة كتابة أو إعادة توجيه أو تعديل الطلب أو رأس الاستجابة، أو عن طريق إرجاع الاستجابة مباشرة، بناءً على الطلب الوارد.

كنظام كامل، يحتوي Next.js على وسائطه الخاصة (middleware) - وهي ميزة مهمة ومستخدمة على نطاق واسع. تشمل سيناريوهات استخدامه العديد من التطبيقات، وأهمها:

إعادة كتابة المسار (Path rewriting)

إعادة التوجيه من جانب الخادم (Server-side redirects)

إضافة معلومات رأس إلى الاستجابة (مثل CSP وغيرها)

الأهم هو: التحقق من الهوية (Authentication) والتفويض (Authorization)

استخدام شائع للبرمجيات الوسيطة هو إجراء التفويض، والذي ينطوي على حماية مسارات معينة بناءً على شروط محددة.

التحقق من الهوية والتفويض: تأكد من هوية المستخدم وفحص ملفات تعريف الارتباط للجلسة (وثائق Next.js) قبل منح الوصول إلى صفحات أو واجهات برمجة التطبيقات المحددة.

مثال: عندما يحاول المستخدم الوصول إلى /dashboard/admin، سيتم أولاً تمرير الطلب عبر البرنامج الوسيط، حيث سيتحقق البرنامج الوسيط من صحة ملف تعريف الارتباط لجلسة المستخدم وما إذا كان لديه الأذونات اللازمة. إذا تم التحقق بنجاح، يقوم البرنامج الوسيط بإعادة توجيه الطلب؛ وإلا، سيقوم البرنامج الوسيط بإعادة توجيه المستخدم إلى صفحة تسجيل الدخول:

أداة التفويض: كود قديم من الدرجة الثمينة

كما قال أحد العظماء: “الكلام رخيص، أظهر لي الخطأ”، دعونا نتجنب الكثير من السرد وننتقل مباشرة إلى الموضوع؛ عند تصفحنا للإصدار القديم من الإطار (v12.0.7)، وجدنا هذه الشفرة:

عندما يستخدم تطبيق Next.js البرامج الوسيطة، يتم استدعاء الدالة runMiddleware. بالإضافة إلى وظيفتها الرئيسية ، تأخذ الوظيفة قيمة رأس الطلب الفرعي x-middleware وتستخدمه لتحديد ما إذا كان يجب تطبيق البرامج الوسيطة. يتم تقسيم قيمة الرأس إلى قائمة باستخدام نقطتين (:) كفاصل، ويتم التحقق من القائمة لمعرفة ما إذا كانت تحتوي على قيمة middlewareInfo.name. هذا يعني أنه إذا أضفنا رأس طلب فرعي x-middleware بالقيمة الصحيحة للطلب ، تجاهل البرنامج الوسيط - بغض النظر عن الغرض منه - تماما وسيتم إعادة توجيه الطلب عبر NextResponse.next() وسيتم إكمال المسار إلى الوجهة الأصلية دون أي تأثير من البرامج الوسيطة. يشبه هذا الرأس وقيمته “المفتاح الرئيسي” الذي يتجاوز جميع القواعد. في هذه المرحلة ، أدركنا أننا وجدنا مشكلة مذهلة ، ويجب إكمال الأجزاء القليلة الأخيرة من اللغز بعد ذلك.

لكي تعمل مفاتيحنا “المفتاح الشامل”، يجب أن تحتوي قيمتها على middlewareInfo.name، لكن ما هي هذه القيمة بالضبط؟

ترتيب التنفيذ مع middlewareInfo.name

قيمة middlewareInfo.name من السهل جداً تخمينها، إنها ببساطة المسار الذي يوجد فيه البرنامج الوسيط. لفهم ذلك، نحتاج إلى معرفة بسيطة عن كيفية تكوين البرنامج الوسيط في الإصدارات القديمة.

أولاً، قبل الإصدار 12.2 - حيث حدث تغيير في اتفاقية الوسيطة في هذا الإصدار - يجب أن تُسمى الملفات _middleware.ts. بالإضافة إلى ذلك، تم تقديم جهاز التوجيه (router) في تطبيق Next.js فقط في الإصدار 13. كان جهاز التوجيه الوحيد الموجود في ذلك الوقت هو جهاز توجيه الصفحات، لذا يجب وضع هذا الملف داخل مجلد الصفحات (محدد لجهاز التوجيه).

بفضل هذه المعلومات، يمكننا استنتاج المسار الدقيق للبرمجيات الوسيطة، وبالتالي تخمين قيمة رأس x-middleware-subrequest. تتكون هذه القيمة فقط من اسم الدليل (أي اسم جهاز التوجيه الفريد الموجود في ذلك الوقت) واسم الملف، وتلتزم باتفاقية التسمية التي تبدأ بشرطة سفلية في ذلك الوقت:

X-وسيطة-طلب فرعي: صفحات/_middleware

عندما نحاول تجاوز تلك المكونات الوسيطة المكونة بشكل منهجي لعملية إعادة توجيه محاولات الوصول من /dashboard/team/admin إلى /dashboard:

نجحنا، لقد اخترقنا ⚔️

يمكننا الآن تجاوز الوسيطة تمامًا وبالتالي تجاوز أي نظام حماية يعتمد عليها، وأشهرها هو التفويض، كما هو موضح في مثالنا أعلاه. هذا الاكتشاف مذهل للغاية، لكن هناك نقاط أخرى تحتاج إلى الاعتبار.

الإصدارات السابقة من 12.2 سمحت بوجود ملفات _middleware في أي مكان في شجرة المجلدات (بدءًا من مجلد pages) وسمحت بترتيب تنفيذها، كما رأينا في لقطة الشاشة للوثائق القديمة التي استعدناها من أرشيف الويب:

ماذا يعني هذا بالنسبة لاستغلال الثغرات لدينا؟

الاحتمالية = عدد المستويات في المسار

لذلك، للوصول إلى /dashboard/panel/admin (محمي بواسطة middleware)، هناك ثلاث إمكانيات لقيمة middlewareInfo.name، وبالمثل هناك ثلاث إمكانيات لقيمة x-middleware-subrequest:

صفحات/_الوسيط

أو

صفحات/لوحة التحكم/_الوسيط

أو

الصفحات / لوحة القيادة / اللوحة / \ _middleware

أداة التفويض: الأمس أصبح قصيدة، واليوم يستحق المزيد

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

ما أدهشنا هو أنه بعد يومين من الاكتشاف الأول، وجدنا أن جميع إصدارات Next.js - بدءًا من الإصدار 11.1.4 - تحتوي على ثغرات! لم يعد الكود في نفس الموقع، كما تغيرت منطق استغلال الثغرات قليلاً.

كما ذكرنا سابقًا، اعتبارًا من الإصدار 12.2، لم يعد الملف يحتوي على خط سفلي، ويجب أن يُطلق عليه ببساطة middleware.ts. بالإضافة إلى ذلك، لم يعد موجودًا في مجلد pages (وهذا مريح بالنسبة لنا، لأنه اعتبارًا من الإصدار 13، تم إدخال جهاز التوجيه app، مما كان سيتسبب في مضاعفة الإمكانيات).

مع وضع ذلك في الاعتبار، فإن الحمولة للإصدارات الأولى بدءًا من الإصدار 12.2 بسيطة جدًا:

مع أخذ ذلك في الاعتبار، فإن الحمولة البسيطة للإصدار الأول بدءًا من الإصدار 12.2 هي:

X-وسيطة-طلب فرعي: البرامج الوسيطة

/src دليل

يجب أن نأخذ في الاعتبار أيضًا أن Next.js توفر إمكانية إنشاء دليل /src:

(وثائق Next.js ) كبديل لوجود تطبيق Next.js خاص أو مجلد الصفحات في الدليل الجذر للمشروع، يدعم Next.js أيضًا نمطًا شائعًا لوضع كود التطبيق في مجلد src. (وثائق Next.js)

في هذه الحالة، سيكون الحمولة هي:

X-وسيطة-طلب فرعي: SRC / البرامج الوسيطة

لذلك، بغض النظر عن عدد المستويات في المسار، هناك احتمالان فقط. هذا يبسط صعوبة استغلال الثغرات المتعلقة بالإصدارات.

في الإصدار الأخير، كان هناك تغيير طفيف آخر (نعدك، هذه هي المرة الأخيرة).

أقصى عمق للتكرار

في الإصدار المحدث، تغيرت المنطق قليلاً، يرجى الاطلاع على هذا الجزء من الشيفرة:

الإصدار 15.1.7

كما كان من قبل، سيقوم النظام بالتحقق من قيمة رأس x-middleware-subrequest، واستخدام النقطتين كفاصل لتشكيل قائمة. لكن هذه المرة، كانت شروط إعادة توجيه الطلب مباشرة - أي تجاهل قواعد الوسيطة - مختلفة:

يجب أن تكون قيمة الثابت depth أكبر من أو تساوي قيمة الثابت MAX_RECURSION_DEPTH (أي 5). أثناء عملية التعيين، في كل مرة يكون فيها قيمة معينة في القائمة subrequests (أي القيم الموجودة في رأس الفصل المفصولة بـ :) تساوي params.name (أي مسار البرنامج الوسيط)، سيزداد الثابت depth بمقدار 1. كما ذُكر سابقًا، هناك احتمالان فقط: middleware أو src/middleware.

لذا، لتجاوز الوسيط، كل ما نحتاجه هو إضافة رأس/قيمة التالية في الطلب:

X-وسيطة-طلب فرعي: البرامج الوسيطة:البرامج الوسيطة:البرامج الوسيطة:البرامج الوسيطة

أو

X-وسيطة-طلب فرعي: SRC/البرامج الوسيطة:SRC/البرامج الوسيطة:SRC/البرامج الوسيطة:SRC/البرامج الوسيطة:SRC/البرامج الوسيطة

ما الغرض الأصلي من هذا الرمز؟

يبدو أن هذا الرمز مصمم لمنع الطلبات المتكررة من الدخول في حلقة لا نهائية.

استغلال الثغرات

نظرًا لأننا نعلم أنك تحب هذا النوع من المحتوى، إليك بعض الحالات الحقيقية من برنامج مكافآت الأخطاء.

تجاوز التفويض/إعادة الكتابة

في هذا المثال، عندما نحاول الوصول إلى /admin/login، نتلقى استجابة 404. من رأس الاستجابة، يمكننا أن نرى أن البرنامج الوسيط نفذ إعادة كتابة المسار لمنع وصول المستخدمين غير المصرح لهم أو غير المناسبين:

لكن باستخدام أداة التفويض الخاصة بنا :

يمكننا الوصول إلى هذه النقطة بدون أي عوائق، وتم تجاهل الوسطاء تمامًا. نسخة Next.js المستهدفة: 15.1.7

تجاوز CSP

هذه المرة يستخدم الموقع البرامج الوسيطة لإعداد - من بين ميزات أخرى - CSP وملفات تعريف الارتباط:

دعنا نتجاوز ذلك:

الإصدار المستهدف من next.js: 15.0.3الإصدار المستهدف من next.js: 15.0.3

ملحوظة: يرجى الانتباه للاختلافات في الحمولة بين الهدفين، أحدهما يستخدم دليل src/ والآخر لا يستخدمه.

تحقيق DoS من خلال تسميم الذاكرة المؤقتة (ماذا؟)

نعم، من الممكن أيضًا تنفيذ هجوم DoS عن طريق تسمم الذاكرة المؤقتة من خلال هذه الثغرة. من الواضح أن هذا ليس ما نبحث عنه أولاً، ولكن إذا لم تكن هناك مسارات حساسة محمية، ولم تكن هناك نقاط استغلال أكثر إثارة للاهتمام، فقد تؤدي بعض الحالات إلى رفض الخدمة الناجم عن تسمم الذاكرة المؤقتة (CPDoS):

افترض أن موقعًا إلكترونيًا يعيد كتابة مسارات المستخدمين بناءً على الموقع الجغرافي، مضيفًا (مثل /en، /fr وما إلى ذلك)، ولا يقدم صفحات أو موارد على المسار الجذري (/). إذا تخطينا البرنامج الوسيط، فسنتجاوز إعادة الكتابة، ونصل في النهاية إلى الصفحة الجذرية. نظرًا لأن المطورين لم يخططوا للسماح للمستخدمين بالوصول إلى الصفحة الجذرية، فلم يتم توفير الصفحة المقابلة، وسنحصل على 404 (أو حسب تكوين/نوع إعادة الكتابة، قد يكون 500).

إذا كان الموقع يستخدم نظام التخزين المؤقت / CDN، فقد يفرض التخزين المؤقت استجابة 404، مما يؤدي إلى عدم توفر الصفحة، مما يؤثر بشكل كبير على قابلية استخدام الموقع.

توضيح

منذ إصدار إعلان الأمان، تلقينا استفسارات من بعض الأشخاص الذين يشعرون بالقلق بشأن أمان تطبيقاتهم ولا يفهمون تمامًا نطاق الهجوم. يجب توضيح أن العناصر القابلة للاختراق هي الوسائط. إذا لم تكن تستخدم الوسائط (أو على الأقل لم تكن تستخدمها لأغراض حساسة)، فلا داعي للقلق (ومع ذلك، يرجى التحقق من جوانب DoS المذكورة أعلاه)، لأن تجاوز الوسائط لن يتجاوز أي آليات أمان فعلية.

وإلا فإن العواقب قد تكون كارثية، نوصيكم بتنفيذ التدابير التوجيهية الواردة في الإعلان الأمني بسرعة.

إشعار أمان - CVE-2025-29927

تصحيح

بالنسبة لـ Next.js 15.x، تم إصلاح هذه المشكلة في 15.2.3

تم إصلاح هذه المشكلة في Next.js 14.x في الإصدار 14.2.25

بالنسبة لإصدار Next.js من 11.1.4 إلى 13.5.6، نوصي بمراجعة الحلول التالية.

حل

إذا لم تتمكن من الترقية إلى إصدار آمن، فإننا نوصي بمنع طلبات المستخدمين الخارجيين التي تحتوي على رأس الطلب x-middleware-subrequest من الوصول إلى تطبيق Next.js الخاص بك.

الخطورة

CVSS: 3.1 / AV: N / AC: L / PR: N / UI: N / S: U / C: H / I: H / A: N (الخطورة: 9.1 / 10 ، حرجة)

مزيد من المعلومات

عند كتابة هذه المقالة، يبدو أن التطبيقات التي تم نشرها على Vercel و Netlify لم تعد تتأثر بهذه الثغرة (تحديث: بسبب وجود عدد كبير من الإنذارات الكاذبة، قامت Cloudflare بتعديل هذه القاعدة لتصبح فعالة فقط عندما يقوم المستخدم بتفعيلها بشكل نشط - لم تتمكن هذه الإنذارات الكاذبة من التمييز بفعالية بين الطلبات من المستخدمين الشرعيين وطلبات المهاجمين المحتملين).

إخلاء المسؤولية

تُنشر هذه الدراسة لأغراض تعليمية فقط، وتهدف إلى مساعدة المطورين على فهم الأسباب الجذرية للمشكلة، أو تقديم الإلهام للباحثين / صائدي الثغرات في أعمالهم البحثية المستقبلية. تُعتبر هذه المقالة مادة مكملة للإعلان الأمني، حيث توفر توضيحات إضافية حول طبيعة الثغرة - لأنه تم الكشف في الإعلان عن رأس الطلبات (بالإضافة إلى الفروقات ذات الصلة) التي أدت إلى هذه الثغرة.

نحن نعلن بوضوح أننا لا ندعم أي استخدام غير أخلاقي لهذا النص.

خاتمة

كما تم التأكيد في هذه المقالة، فإن هذه الثغرة موجودة في الكود المصدري لـ Next.js منذ عدة سنوات، وقد تغيرت مع تطور البرامج الوسيطة وإصداراتها. يمكن أن تحتوي أي برمجيات على ثغرات خطيرة، ولكن عندما تؤثر على واحدة من أشهر الأطر، فإنها تصبح خطيرة بشكل خاص وقد تؤدي إلى عواقب وخيمة على النظام البيئي الأوسع. كما ذكر سابقًا، في وقت كتابة هذه المقالة، كان عدد التنزيلات الأسبوعية لـ Next.js قريبًا من 10 ملايين. يتم استخدامه على نطاق واسع في مجالات حيوية تتراوح من الخدمات المصرفية إلى blockchain. عندما تؤثر الثغرة على الميزات الناضجة التي يعتمد عليها المستخدمون (مثل التفويض والمصادقة)، فإن المخاطر تكون أكبر.

قضى فريق Vercel بضعة أيام في حل هذه الثغرة، ولكن من الجدير بالذكر أنه بمجرد أن أدركوا المشكلة، تم تقديم الإصلاح ودمجه في غضون ساعات قليلة في الإصدار الجديد (بما في ذلك عمليات النقل الخلفية).

الخط الزمني :

27 فبراير 2025: تم الإبلاغ عن الثغرة للجهات المسؤولة (في ذلك الوقت كنا نعتقد أن الإصدارات من 12.0.0 إلى 12.0.7 فقط هي المتأثرة، وقد تم الإشارة إلى ذلك في التقرير).

1 مارس 2025: تم إرسال البريد الإلكتروني الثاني، موضحًا أن جميع الإصدارات تحتوي على ثغرات، بما في ذلك أحدث إصدار مستقر.

5 مارس 2025: تم استلام الرد الأولي من فريق Vercel، الذي يشير إلى أن الإصدار 12.x لم يعد مدعومًا (ربما لم يتم قراءة نموذج إشعار الأمان المرفق في البريد الإلكتروني الثاني، ولم يتم الانتباه إلى أن جميع الإصدارات متأثرة).

5 مارس 2025: إرسال بريد إلكتروني مرة أخرى، يرجى من الفريق مراجعة البريد الإلكتروني الثاني ونموذج الإشعار الأمني في أقرب وقت ممكن.

11 مارس 2025: أعد إرسال البريد الإلكتروني مرة أخرى لتأكيد ما إذا كانت المعلومات الجديدة قد تم اعتمادها.

17 مارس 2025: استلمنا رد فريق Vercel، يؤكد أنه تم اعتماد المعلومات ذات الصلة.

18 مارس 2025: تم استلام بريد إلكتروني من فريق Vercel، يفيد بأن التقرير قد تم قبوله، وأن تصحيح الأخطاء قد اكتمل. بعد ساعات قليلة تم إصدار النسخة 15.2.3 التي تتضمن التصحيح (وتتضمن أيضًا تصحيح التراجع).

21 مارس 2025: تم إصدار إشعار الأمان رسميًا.

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

REACT‎-9.85%
شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
  • أعجبني
  • تعليق
  • إعادة النشر
  • مشاركة
تعليق
0/400
لا توجد تعليقات
  • Gate Fun الساخن

    عرض المزيد
  • القيمة السوقية:$0.1عدد الحائزين:1
    0.00%
  • القيمة السوقية:$3.57Kعدد الحائزين:1
    0.00%
  • القيمة السوقية:$3.57Kعدد الحائزين:1
    0.00%
  • القيمة السوقية:$3.57Kعدد الحائزين:1
    0.00%
  • القيمة السوقية:$3.57Kعدد الحائزين:1
    0.00%
  • تثبيت