
إصلاح يحافظ على السلوك لثغرة CVE-2025-60876 لحقن رؤوس HTTP في BusyBox wget، مع إثبات المفهوم، وتصحيح ترميز النسبة المئوية، وقطع أثرية لتقديمها للمشروع الأصلي.
إصلاح يحافظ على السلوك لثغرة CVE-2025-60876، وهي ثغرة حقن في رأس HTTP في wget من BusyBox، بالإضافة إلى إثبات المفهوم الذي يوضحها والمواد اللازمة لتقديم الإصلاح إلى المصدر الرئيسي لـ BusyBox.
يقوم wget من BusyBox بنسخ مسار URL والاستعلام في سطر طلب HTTP حرفياً. يمكن لعنوان URL يحمل CR خام (0x0D) أو LF (0x0A) أو بايت تحكم آخر أن يقسم سطر الطلب ويحقن رؤوساً يتحكم بها المهاجم. كما أن المسافة (0x20) لها نفس التأثير: فهي تكسر إطار METHOD SP request-target SP HTTP/1.1.
المتأثر: BusyBox حتى الإصدار 1.37.0 (pkgver المُرسَل في كل فرع Alpine مدعوم). تم الإبلاغ عنها في القائمة البريدية لـ BusyBox في أغسطس 2025؛ تم تعيين CVE كـ CVE-2025-60876 (CVSS 6.5 من NVD، متوسطة).
تم اقتراح تصحيحين بالفعل في المصدر الرئيسي (Takeuchi Yuma، أغسطس 2025؛ Radoslav Kolev، نوفمبر 2025). كلاهما يرفض عنوان URL المخالف ويستدعي bb_error_msg_and_die. هذا يوقف الحقن، ولكنه أيضاً يرفض مسافة عادية، لذا فإن عنوان URL مثل الذي كان يعمل سابقاً يسبب خطأ الآن. هذا التراجع هو السبب في عدم اعتماد الإصلاح في المصادر الفرعية. تنتظر Alpine تراجعها على هذا ().
http://example.org/foo barيتعامل هذا الإصلاح مع المسار والمضيف بشكل مختلف، بما يتوافق مع كيفية عمل GNU wget و curl.
المسار: percent_encode_target() في networking/wget.c يقوم بترميز بايتات التحكم (0x00 إلى 0x1f) والمسافة (0x20) و DEL (0x7f) في طلب الهدف قبل بناء سطر الطلب:
http://example.org/foo bar كـ /foo%20bar، بما يتوافق مع GNU wget و curl. لا تراجع.% الموجودة، لذا لا يتم إعادة ترميز مسار تم ترميزه بالفعل.المضيف: يتم رفض نفس البايتات في مضيف URL. لا يمكن أن يحتوي اسم المضيف شرعياً على أحرف تحكم أو مسافة، ولا يتم تعريف ترميز النسبة لمكون السلطة. هذا مهم في وضع الوكيل: يتم وضع المضيف في طلب الهدف بصيغة مطلقة (GET http://host/path) وفي رأس Host: ولكنه لا يتم حله محلياً، لذا فإن CR أو LF خام في المضيف كان سيسبب حقناً. GNU wget (منذ CVE-2017-6508) و curl يرفضان أيضاً أحرف التحكم في المضيف.
يقتصر التغيير على networking/wget.c ويضيف دالة مساعدة واحدة.
خارج النطاق: قناة التحكم FTP (ftpcmd ترسل target->path واسم المستخدم/كلمة المرور خام، وهي مهمة معترف بها من المصدر الرئيسي) هي فئة حقن منفصلة، وليست جزءاً من CVE-2025-60876، ولا يتم معالجتها هنا. يجب تتبعها بشكل منفصل.
بُني ضد BusyBox 1.37.0 بنفس التهيئة التي يستخدمها Alpine (CONFIG_WERROR و CONFIG_TC معطلة). يستمع مستقبل محلي للبايتات الدقيقة التي يضعها wget على الخط.
| رابط الإدخال | النسخة الأصلية 1.37.0 | بعد التصحيح |
|---|---|---|
/x + CRLF + Evil: injected | يصل Evil: injected كرأس حقيقي (ضعيف) | GET /x%0D%0AEvil:%20injected HTTP/1.1، لا يوجد رأس محقون |
/foo bar | يرسل مسافة حرفية | GET /foo%20bar HTTP/1.1 (لا تراجع) |
/foo%20bar (مُرمَّز بالفعل) | بدون تغيير | GET /foo%20bar HTTP/1.1 (ليس %2520) |
/normal | بدون تغيير | GET /normal HTTP/1.1 (بدون تغيير) |
وكيل، المضيف = h + CRLF + PInjected: 1 | يصل PInjected: 1 كرأس حقيقي (ضعيف) | ينتهي مع bad character in URL host، لا شيء يُرسل |
وكيل، المضيف = example.test | عادي | GET http://example.test/p HTTP/1.1 (بدون تغيير) |
الالتقاط الكامل: test/poc-output.txt. جميع اختبارات BusyBox testsuite/wget الأربعة تنجح مع البناء المُصحح (test/testsuite-output.txt)؛ الإخفاقات الأخرى في مجموعة الاختبارات الكاملة المذكورة هناك غير مرتبطة (mount/taskset يحتاج صلاحية الجذر، وبعض الشذوذ في حاويات مقيدة معروفة). تأثير الحجم على aarch64 defconfig هو +185 بايت (wget_main +142، .rodata +43، لا رموز مضافة أو محذوفة)، تم قياسه باستخدام scripts/bloat-o-meter ومسجل في cover-letter.txt.
| الملف | ما هو |
|---|---|
wget-cve-2025-60876.patch | الإصلاح كـ git format-patch ضد BusyBox networking/wget.c، جاهز للإرسال |
commit-message.txt | رسالة الالتزام (أيضاً رأس التصحيح) |
cover-letter.txt | رسالة غلاف [PATCH v3] للقائمة البريدية التي تعيد إحياء النقاش الحالي |
apply_fix.py | مولد يطبق التغيير على networking/wget.c (يُستخدم لإنتاج التصحيح) |
test/serve_once.py | مستقبل اتصال واحد يعيد طلب HTTP الخام |
test/driver.sh | يبني BusyBox الأصلي والمصحح ويشغل إثبات المفهوم المباشر وعبر الوكيل قبل وبعد |
test/finalize.sh | تشغيل كامل: إثبات المفهوم قبل وبعد، bloat-o-meter، testsuite/wget، وإعادة توليد التصحيح |
test/poc-output.txt | بايتات الطلب الملتقطة قبل وبعد (مباشر ووكيل) |
test/testsuite-output.txt | نتائج BusyBox testsuite/wget ضد البناء المُصحح |
يعمل test/finalize.sh داخل حاوية alpine:edge مع Docker ويعيد إنتاج كل شيء (إثبات المفهوم، الحجم، مجموعة الاختبارات، التصحيح):
docker run --rm -v "$PWD:/work" alpine:edge sh /work/test/finalize.sh
يقوم بتنزيل BusyBox 1.37.0، بناءه الأصلي (يظهر الحقن مباشرة وعبر وكيل)، تطبيق الإصلاح، إعادة البناء، إعادة تشغيل حالات الطلب أعلاه، تشغيل bloat-o-meter ومجموعة اختبارات wget، وكتابة التصحيح. test/driver.sh هو متغير أخف يقتصر على إثبات المفهوم.
BusyBox هو مشروع قائمة بريدية. يُرسل الإصلاح إلى [email protected] عبر git send-email، كرد [PATCH v3] على موضوع Radoslav Kolev في نوفمبر 2025، مع الإشادة بالمبلغين والمراجعين السابقين. انظر cover-letter.txt. الإصلاح مرخص تحت GPLv2، نفس ترخيص BusyBox.