يُظهر بحث جديد أن تجزئة التزام Git الموقع ليس الاسم الفريد من نوعه الذي يفترضه الكثير من عالم البرمجيات. بالنظر إلى أي التزام موقّع، يمكن لشخص ليس لديه مفتاح التوقيع أن يسك التزامًا ثانيًا بنفس الملفات والمؤلف والتاريخ وتوقيع صالح، ولا يزال GitHub يختم “تم التحقق منه”.

كل شيء سيتحقق منه المراجع من التطابقات. تجزئة الالتزام لا. وهذا مهم لأن العديد من الأنظمة تتعامل مع تجزئة الالتزام التي تم التحقق منها كاسم دائم وفريد ​​لمحتوياتها.

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

يمكن للمرآة المخترقة أو المعادية تسليم المستنسخين التزامات موقعة بشكل صحيح والتي تختلف تجزئاتها عن تلك الموجودة في الصياغة الأساسية.

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

لا يوجد CVE ولا نصيحة للموردين، ولا شيء يمكن تغييره في الريبو الخاص بك: الخلل يكمن في كيفية تحديد الصياغة لما تعنيه كلمة “تم التحقق”، والإصلاح يقع على جانب الصياغة.

يأتي هذا العمل من جاكوب جينسين، طالب الدكتوراه في جامعة كارنيجي ميلون ومدقق التشفير في Cure53. تأتي ورقته البحثية المكونة من خمس صفحات، والتي تم نشرها على arXiv في 2 يوليو، مزودة بأداة عامة تدير جميع الهجمات الثلاثة، بالإضافة إلى مستودعين تجريبيين حيث لا تزال الالتزامات الخاطئة تظهر “تم التحقق” على GitHub.

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

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

تغطي المسارات الثلاثة كل مخطط GPG يتحقق منه GitHub، بالإضافة إلى S/MIME:

  • مفاتيح ECDSA: اقلب التوقيع بقطعة كلاسيكية من جبر المنحنى الإهليلجي (حول القيمة s إلى n – s). كلا النموذجين صالحان. يؤدي هذا إلى اجتياز التزام التحقق من git المحلي ويحصل على شارة GitHub.
  • مفاتيح RSA وEdDSA: أضف حقلاً إضافيًا تم تجاهله إلى القسم “غير المجزأ” الخاص بالتوقيع، وهو الجزء الذي لا يغطيه التوقيع عمدًا. لا يزال يتم التحقق من التوقيع، ولكن تتغير بايتات الالتزام وتجزئةه. يقبله كل من Local وGitHub.
  • مفاتيح S/MIME (X.509): أعد كتابة حقل الطول في بنية DER الخاصة بالتوقيع إلى نموذج أطول وغير قياسي. يرفضه فحص محلي صارم (عبر gpgsm)، لكن GitHub لا يزال يضع علامة “تم التحقق منه”، وكلاهما تقوم الأداة بإعادة إنتاجه.

تشترك المسارات الثلاثة في أداة تمكين واحدة: لا يقوم GitHub بتطبيع التوقيع قبل التحقق منه. لا يوجد تشفير صارم على S/MIME، ولا يتم تجريد حقول OpenPGP هذه، ويتم قبول قيم ECDSA غير الأساسية كما هي.

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

لنكون واضحين: هذا ليس تصادمًا تجزئة. إنه لا يكسر SHA-1 أو SHA-256، ولا علاقة له بانتقال Git إلى SHA-256. لا أحد يفرض التزامين مختلفين لمشاركة تجزئة واحدة؛ بل هو العكس، التزام واحد يمكن كتابته بعدة طرق صالحة، كل منها بتجزئة خاصة بها.

الخطوة الأساسية قديمة. لقد حاربت Bitcoin نفس تناظر ECDSA منذ سنوات، عندما كان بإمكان أي شخص قلب قيمة s في توقيع المعاملة وتغيير معرف المعاملة دون مفتاح المالك. كان الإصلاح هو قبول النموذج “منخفض S” فقط، وبعد ذلك نقل التوقيعات من المعرف باستخدام SegWit.

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

تربط الورقة أيضًا هذا الأمر بعمليات اختطاف علامات GitHub Actions الأخيرة، وهجمات tj-actions/changed-files لعام 2025، وهجمات الإجراءات التافهة لعام 2026 (تستشهد بالأخيرة). بعد ذلك، كانت النصيحة بسيطة: قم بتثبيت علامة التجزئة الكاملة، وليس علامة منقولة. ولا تزال هذه النصيحة قائمة.

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

إذن من عليه أن يفعل شيئًا؟ ليس المطور الذي يقوم بتثبيت إجراء أو وحدة؛ لا يزال التجزئة المثبت يجلب الرمز الصحيح. العمل هو للحدادة. تقول الصحيفة أنه يجب عليهم إضفاء الطابع القانوني على التوقيعات قبل الوثوق بها.

الأدوات التي تحظر أو تزيل التكرارات أو تسجل المصدر من خلال تجزئة الالتزام يجب أن تفعل الشيء نفسه، حيث يتم التحقق والتحديد الأساسي أولاً بدلاً من الوثوق في التجزئة الأولية للكائن الموقع الذي يمكن للمهاجم إعادة تشفيره. لا يتم كشف جميع الأنظمة بشكل متساوٍ: فالمخططات التي تثبت أيضًا تجزئة مستقلة للملفات التي تم جلبها، مثل اشتقاقات المخرجات الثابتة لـ Nix، تحتفظ بنقطة توقف؛ تلك التي تتوقف عند تجزئة الالتزام التي تم التحقق منها لا تفعل ذلك.

يقول جينيسين إنه أبلغ عن هذه المشكلة إلى GNU وGit في يناير وإلى GitHub في مارس، وأنه حتى تاريخ نشر الصحيفة، لم يعالجها Git ولا أي شركة Forge. إن الإصلاح من جانب الصياغة مفهوم جيدًا، والمكان الواضح للبدء هو حالة S/MIME، حيث لا يزال GitHub يقبل ما يرفضه الفحص المحلي الصارم.

شاركها.
اترك تعليقاً