ثغرة TokenGuard الحرجة في Laravel: تحقق من تطبيقك وحدّث الآن
ثغرة TokenGuard في Laravel (CVSS 9.2) تسمح بانتحال أي مستخدم على MySQL وMariaDB. اعرف هل تطبيقك متأثر وكيف تحدّث إلى 12.68 أو 13.29.
نشر فريق Laravel في 19 أكتوبر 2026 تحذيرًا أمنيًا بدرجة Critical عن ثغرة في حارس المصادقة TokenGuard، وهو الحارس الذي يعمل عند ضبط 'driver' => 'token' في config/auth.php. إن كان لديك API يعتمد على هذا الحارس فقد يستطيع مهاجم بلا أي بيانات دخول أن يدخل باسم مستخدم موجود. الخبر الجيد أن الإصلاح متاح، وأن التحقق من تعرّضك للثغرة يستغرق دقائق.
ما الذي حدث بالضبط في ثغرة TokenGuard؟
التحذير مسجّل برقم GHSA-f9x3-7vq9-cph6 ورقم CVE-2026-114509، وقد اكتشفه الباحث KIKOmanasijev بحسب صفحة التحذير. وصفه الرسمي باختصار: يمكن تجاوز TokenGuard عندما يُستخدم كحارس API قائم على الـ token، فيصادق المهاجم كمستخدم موجود دون أن يعرف الـ token الصحيح.
الثغرة تعتمد على قاعدة البيانات. على MySQL وMariaDB يمكن إرسال قيمة اعتماد (credential) غير نصية مصاغة بعناية، فتعالجها عملية البحث عن المستخدم بشكل خاطئ، وبدل أن يفشل الاستعلام يطابق سجل مستخدم آخر. النتيجة المذكورة في التحذير: استيلاء على الحساب في أي route يحميه الحارس المتأثر.
صفحة التحذير لا تشرح تفاصيل الاستغلال التقنية أكثر من ذلك، ولن نخمّن نحن هنا. المهم عمليًا أن الشروط محددة، وأن الإصلاح بحسب تغطية Laravel News يرفض أي token غير نصي قبل أن يصل إلى الاستعلام.
هل تطبيقك متأثر؟
تتحقق كل الشروط التالية معًا:
- تستخدم حارسًا بـ driver من نوع
token. - قاعدة بياناتك MySQL أو MariaDB.
- إصدار
laravel/frameworkأقل من 12.68.0 (فرع 12.x) أو أقل من 13.29.0 (فرع 13.x).
افتح config/auth.php وابحث عن شيء كهذا:
'guards' => [
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
وفق ما ورد في Laravel News، حزمتا Sanctum وPassport تستخدمان حراس مصادقة خاصة بهما ولم تُذكرا ضمن الثغرة. لكن لا تكتفِ بالافتراض: افحص config/auth.php وتأكد أن أي route لا يمرّ عبر حارس token من دون قصد، خصوصًا في المشاريع القديمة أو التي ورثتها من فريق آخر.
كيف تحدّث؟
الإصدارات المصححة هي 12.68.0 و13.29.0 وما بعدهما. شغّل:
composer update laravel/framework
composer audit
ثم تأكد من الإصدار المثبّت:
composer show laravel/framework | grep versions
الأمر composer audit يقارن الحزم المثبّتة بقاعدة التحذيرات المعروفة، ومن الجيد جعله خطوة ثابتة في الـ CI. التحذير لا يذكر أي حل بديل (workaround)، فالترقية هي العلاج الوحيد الموصوف. وإن كنت على إصدار أقدم من 12.x فعليك الانتقال إلى فرع مدعوم أولًا، لأن التصحيحات تخص فرعي 12.x و13.x فقط.
لاحظ تفصيلًا في التواريخ: صفحة GitHub تُظهر أن وسم v13.29.0 صدر في 25 أغسطس، بينما نُشر التحذير علنًا في 19 أكتوبر. هذا نمط شائع، إذ يُنشر التحذير بعد أن تتاح الإصلاحات بوقت. وتذكر تغطية Laravel News أن الإصدارين 12.68.0 و13.29.0 صدرا في التاريخ نفسه (25 أغسطس). معنى ذلك أن من يحدّث بانتظام ربما يكون محميًا فعلًا، ومن ثبّت الإصدارات قد يكون مكشوفًا منذ شهرين.
تحذير ثانٍ نُشر في اليوم نفسه
صدر في 19 أكتوبر أيضًا تحذير بدرجة Moderate (CVSS 6.5) برقم GHSA-5wcm-3v2w-8362 وCVE-2026-114508. يتعلق بمعالجة تضمين العلاقات في بعض نقاط القراءة، وقد يسمح لطلب قراءة فقط بتنفيذ عملية حذف مدمّرة على جدول مرتبط، أي فقدان بيانات من دون صلاحية كتابة. المتأثر بحسب التحذير: من 12.45.0 حتى ما قبل 12.68.0، وما قبل 13.27.0 في الفرع 13. وتفاصيل الشروط لم تُنشر. الترقية إلى 12.68.0 أو 13.29.0 تغطي الثغرتين معًا.
لماذا تشكّل القيم غير النصية خطرًا في المصادقة؟
الفكرة العامة، بمعزل عن تفاصيل هذه الثغرة التي لم يشرحها التحذير، أن المصادقة بالـ token تقوم على سؤال بسيط: هل يوجد مستخدم يملك هذا الـ token؟ هذا السؤال يفترض أن القيمة القادمة من الطلب نص. فإذا وصلت مصفوفة أو كائن بدل النص (وهو ممكن لأن إطار العمل يحلل JSON وحقول الاستعلام إلى أنواع PHP مختلفة)، فقد يتغير معنى الاستعلام الذي يبنيه الكود أو طريقة مقارنة قاعدة البيانات للقيمة. وقد يكون هذا سبب ارتباط الثغرة بقواعد بعينها (MySQL وMariaDB)، لأن سلوك المقارنة وتحويل الأنواع يختلف من قاعدة إلى أخرى؛ وهذا تفسير عام وليس ما ينص عليه التحذير.
الدرس العملي أن التحقق من النوع يجب أن يحدث عند الحدود: أول مكان تدخل فيه القيمة إلى نظامك، لا بعد أن تصل إلى طبقة الاستعلام.
قائمة مراجعة بعد الترقية
- تأكد أن
composer.lockيحتوي الإصدار المصحح وأنه نُشر فعلًا على الخوادم كلها، لا على جهازك فقط. - أعد تشغيل الـ queue workers وPHP-FPM وOctane إن كنت تستخدمه، حتى لا يبقى الكود القديم في الذاكرة.
- شغّل اختبارات المصادقة في مشروعك، وأضف اختبارًا يرسل token بصيغة غير نصية ويتوقع رفضًا بحالة 401.
- إن كنت تدير عدة تطبيقات، كرر الفحص على كل واحد منها بدل الاكتفاء بالتطبيق الرئيسي.
ما الذي تتعلمه من هذه الحادثة؟
- لا تعتمد على الأنواع الضمنية في المصادقة. أي قيمة قادمة من الطلب قد لا تكون نصًا؛ تحقق من نوعها (
is_string) قبل أن تصل إلى طبقة البيانات. - فضّل Sanctum أو Passport لتوثيق الـ API بدل
tokendriver البسيط، فهما أكثر نضجًا وتوفران إدارة للصلاحيات وانتهاء الصلاحية. هذا توجيه عام وليس جزءًا من التحذير. - اجعل
composer auditجزءًا من خط النشر حتى تعرف بالثغرات المعلنة دون انتظار خبر. - راجع سجلات الدخول. إن كنت مكشوفًا قبل الترقية، فابحث في سجلات الـ API عن طلبات مصادَق عليها بقيم token غريبة الشكل أو من عناوين غير معتادة؛ لم يرد في التحذير أي مؤشر اختراق محدد، لذا هذه مجرد ممارسة احترازية.
الخلاصة
إن كان في config/auth.php حارس token، وقاعدتك MySQL أو MariaDB، فرقّ laravel/framework إلى 12.68.0 أو 13.29.0 على الأقل اليوم، ثم شغّل composer audit وراجع السجلات. وإن لم تستخدم هذا الحارس فالترقية تبقى مفيدة لأنها تغطي ثغرة JSON:API الثانية.