
مجموعة أدوات جنائية ومهارات وكيل للتحقيق في Rails Active Storage/libvips CVE-2026-66066: تكتشف مؤشرات blob المصممة ببراعة، ونوافذ التعرض، وتسريب البيانات.
أدوات ومنهجية للإجابة عن سؤالين بخصوص تطبيق Rails و CVE-2026-66066، ثغرة القراءة التعسفية للملفات في Active Storage وlibvips المعروفة باسم KindaRails2Shell:
الاستشارة الأمنية GHSA-xr9x-r78c-5hrm شرحت الثغرة وحددت الإصدارات المُرقَّعة، لكنها لم تفصح عن تفاصيل كافية لتقييم هذين السؤالين. هذا المشروع يهدف إلى المساعدة في ذلك.
هذا مستودع توثيق ومهارات وليس مكتبة. لا شيء هنا يُثبَّت في تطبيقك. يقرأه الوكيل ويعمل على تطبيقك المستنسخ في مكان آخر، والسكربت الوحيد الذي يعمل في بيئة الإنتاج هو ملف واحد مكتفٍ ذاتيًا تنسخه إلى حاوية.
يقرر Rails أن كتلة بيانات (blob) قد تخضع لمعالجة الصور من خلال قراءة عمود content_type
الذي يسمح الرفع المباشر للعميل بتعيينه دون أن تُفحص البايتات إطلاقًا.
ثم يقرر libvips ما هو الملف فعليًا عبر استشعار بايتات السحر (magic bytes). ملف
تدّعي بايتاته العشر الأولى أنه MATLAB 5.0 يُوجَّه إلى محمّل MATLAB في libvips،
الذي يسلّمه إلى libmatio، الذي يوزّع على نطاق بايتات مختلف
ويجد MAT 7.3، وهو HDF5. تتيح قائمة الملفات الخارجية في HDF5 أن تعيش بايتات مجموعة بيانات
في ملف آخر يُحدَّد بالمسار والإزاحة، لذا فإن عرض "الصورة" يقرأ ملفًا
اختاره المهاجم من الخادم ويعيد محتوياته كبكسلات. نفس
الالتباس، مرتين، على طبقتين لا تستطيع أي منهما رؤية حقول الأخرى.
يتتبع reference/the-attack.md سلسلة الاستدعاء كاملة، من الطلب الوارد
إلى النقطة التي يفتح فيها libmatio الملف الهدف، مع تمييز
المفاصل الأربعة الحاملة. ثم يشرح reference/the-investigation.md لماذا يكون الهجوم
قابلًا للتحقيق أصلًا: فهو يترك ثلاثة آثار متزايدة القوة،
وأقواها هو المتغير المُصيَّر (rendered variant)، الذي يحتفظ بالبايتات المسروقة
كقيم بكسلات في مخزن الكائنات الخاص بك.
تعمل المهارتان بالترتيب. الأولى تنتج نافذة التعرض؛ والثانية لا يمكن أن تبدأ بدونها.
| المهارة | السؤال | الناتج |
|---|---|---|
kr2s-was-i-vulnerable | هل كان هذا التطبيق عرضة للثغرة يومًا ما؟ | نافذة تعرض والحقائق التي يحتاجها المسح |
kr2s-was-i-exploited | هل استخدمها أحد، وماذا حصل عليه؟ | تحليل جنائي مكتوب |
كلتاهما مكتوبتان لوكيل، وكلتاهما قابلة للقراءة من قبل شخص يريد القيام
بالعمل يدويًا. لكل منهما نقطة دخول SKILL.md وreferences/guide.md
يحتوي على العملية الفعلية، وفحوصات التقييم، وأنماط الفشل.
إذا كنت قد رقّعت وتريد معرفة ما إذا كان يجب أن تهتم، فشغّل الأولى. مخرجاتها نافذة زمنية وليست نعم أو لا، لأنه بالنسبة لمعظم من يقرأ هذا فإن الإجابة بصيغة المضارع هي "لا، لقد رقّعنا"، والإجابة المفيدة هي أي السنوات التي سيتعين على التحقيق تغطيتها.
استنسخ هذا المستودع واحتفظ بالنسخة المستنسخة. تتشارك المهارتان مستندات المرجع
في reference/، وتقرأ أدلتهما تلك المستندات عبر مسار نسبي للمستودع، لذا فإن دليل مهارة
منسوخ في مكان ما بمفرده سينتهي إلى طريق مسدود.
أسهل شيء هو بدء وكيلك داخل النسخة المستنسخة وإخباره بمكان
تطبيقك. يوجّهه AGENTS.md من هناك، بما في ذلك الجزء الذي يخطئ فيه الناس،
وهو أن هذا المستودع هو الأداة وليس الموضوع.
وإلا، فأشر إلى الملف وقل ذلك، وهو ما ينجح في أي وكيل يمكنه قراءة الملفات المحلية:
Read /path/to/rails-forensics-CVE-2026-66066/skills/kr2s-was-i-vulnerable/SKILL.md
and follow it. My application is at /path/to/my-app.
في Claude Code يمكنك بدلاً من ذلك تثبيتها بحيث تُفعَّل من تلقاء نفسها، عن طريق إنشاء روابط رمزية بدلاً من النسخ، مما يُبقيها مشيرة إلى النسخة المستنسخة:
ln -s "$PWD/skills/kr2s-was-i-vulnerable" ~/.claude/skills/
ln -s "$PWD/skills/kr2s-was-i-exploited" ~/.claude/skills/
استخدم .claude/skills/ داخل مشروع بدلاً من ~/.claude/skills/ إذا كنت
تفضّل حصرها على تطبيق واحد.
في كلتا الحالتين، أخبر الوكيل بمكان تطبيقك. تنص المهارات صراحةً على أن هذا المستودع والتطبيق قيد الفحص جذران مختلفان، وأنه يجوز لها قراءة الثاني لكن لا يجوز لها الكتابة فيه أبداً.
AGENTS.md orientation for an agent started in this directory
reference/the-attack.md how the vulnerability works, traced call by call
reference/the-investigation.md why an investigation is possible, and where it runs out
skills/ the two skills
RUNBOOK.md operator's guide to the scanner: flags, verdicts, resuming
lib/crafted_mat_file.rb the detector
bin/ the scanner and three analysis utilities
test/ the test suite
المستندان المرجعيان هما النصف المكتوب بلغة واضحة من هذا المستودع، وهما قائمان بذاتهما. اقرأهما إذا أردت فهم المشكلة، وشغّل المهارات إذا أردت إجابة عن تطبيق معيّن.
يُولَّد bin/kr2s_scan_active_storage_blobs.rb من lib/ بواسطة rake build
ويُثبَّت في المستودع، لذا فإن تشغيله في بيئة الإنتاج لا يحتاج إلى خطوة بناء ولا إلى
ملف ثانٍ.
يحدّد lib/crafted_mat_file.rb الملف المصنوع الذي يتطلبه هذا الهجوم. فهو
يقرأ حقلَي ترويسة من أول 128 بايتًا من كائن ولا يحتاج
إلى أي شيء آخر، ولهذا يمكن للمسح تصنيف مرشّح من قراءة محدّدة النطاق
بدلًا من تنزيله. يشرح reference/the-attack.md أي الحقول ولماذا لا ينتج أي كاتب
شرعي هذا المزيج.
لا يشحن هذا المستودع عمدًا أي شيفرة تبني ملفات مصنوعة، ولا أي
ملفات مصنوعة. تُصنّع اختبارات الكاشف الـ 128 بايتًا من الترويسة التي
تحتاجها بلغة Ruby خالصة، وهي كل ما يقرأه الكاشف. يصف reference/the-attack.md
البنية بالكامل، لذا لا شيء يُحجب عن قارئ
يحاول فهم الهجوم. ما يُحجب هو مولّد عامل يمكن
إعادة توجيهه إلى مسار عشوائي بتغيير وسيط واحد.
المشمول: Active Storage، في التطبيقات التي تستخدم معالج المتغيّر :vips،
حيث كانت سجلات المتغيّرات متتبَّعة.
غير المشمول: أي مكان آخر يسلّم فيه التطبيق ملفات مقدَّمة من المستخدم
إلى libvips. مكتبات الرفع الأخرى، وعملاء مخازن الكائنات المباشرون، وأنظمة
الصور الرمزية أو الشعارات المخصّصة، كلها تحتاج إلى مسح خاص بها، ولن يقوم
الماسح هنا بذلك. سيجعلك kr2s-was-i-vulnerable تعدّدها حتى تُسمّى
بدلًا من حذفها بصمت من الاستنتاج.
النتيجة النظيفة من هذه الأدوات دليل قوي، وليست برهانًا. تقول المهارتان ذلك، مرارًا وتحديدًا، وقالب التحليل يحتوي على قسم للحدود غير اختياري.
جاء هذا من تحقيق حقيقي في 37signals، مسحًا مخزن Active Storage إنتاجيًا كبيرًا على مدى الفترة الكاملة التي وُجدت فيها الثغرة. حدّدت الأدوات بشكل صحيح ملفات الاختبار التي رفعها الباحثون الأمنيون الذين أبلغوا عن العيب، وهو الدليل الخارجي الوحيد المتاح على أن الكاشف يجد ما يُفترض أن يجده.
التحليل النموذجي في kr2s-was-i-exploited/references/analysis-template.md
خيالي. إنه مستوحى من التحليل الحقيقي، لكن كل معرّف وعنوان
وتاريخ فيه مختلق.
خُذ أرقام إصدارات Rails المُرَقَّعة من الاستشارة بدلًا من أي شيء مكتوب هنا.
mise exec -- rake # build and test
MIT. انظر LICENSE.