
CVE-2017-14948 لـ D-Link 880 Firmware
في هذا الشرح الموجز سنرى بعض الأخطاء البرمجية التي اكتشفتها في منتجات D-Link. تقدم D-Link مجموعة واسعة من المنتجات، بما في ذلك العديد من موديلات أجهزة التوجيه المختلفة، التي تعمل بإصدارات برمجية (firmware) متنوعة. في هذا المستند سأتناول إصدارات البرمجيات التالية: DIR-880L وDIR-868L وDIR-890L وDIR-885L وDIR-895L. بدون مزيد من المقدمات، لنبدأ.
نظرًا لأنني لم أمتلك أيًا من أجهزة توجيه D-Link، وأنهم يوفرون وصولًا مجانيًا إلى برمجياتهم، قررت البحث عن الأخطاء بالاعتماد فقط على التحليل الثابت (static analysis). لاحظ أنني في هذا القسم سأشير إلى برمجيات DIR-880L، أما بقية البرمجيات فلها هياكل مشابهة.
بعد تنزيل وفك ضغط برمجيات DIR-880L، اكتشفت أن برمجياتها تحتوي على نظام ملفات كامل من نوع squashFS، يحتوي على حوالي 2160 ملفًا. وبما أنني لم أرغب في فحص كل ملف على حدة، بدأت بالبحث عن الملف الذي يتعامل مع مدخلات المستخدم.
بعد تحليل ملفات الإعدادات والبحث عن ترويسات HTTP المعروفة، قمت في النهاية بتضييق نطاق التركيز على ثلاثة ملفات تنفيذية، وأخيرًا على ملف واحد: fileaccess.cgi.
فيما يلي التفكيك (disassembly) للدالة المعرضة للثغرة:
signed int __fastcall content_type(char *a1)
{
char *dest; // [sp+4h] [bp-10h]@1
const char *haystack; // [sp+Ch] [bp-8h]@1
char *haystacka; // [sp+Ch] [bp-8h]@3
dest = a1;
haystack = getenv("CONTENT_TYPE");
if ( !haystack )
return -22;
haystacka = strstr(haystack, "boundary=");
if ( !haystacka )
return -22;
strcpy(dest, haystacka + 9);
return 0;
}
في الكود أعلاه، محتوى المتغير 'CONTENT_TYPE' (الذي يشير إليه المتغير haystack) يتحكم فيه المستخدم (عبر ترويسة طلب HTTP). يتم نسخ محتواه، بعد الكلمة المفتاحية 'boundary'، إلى مخزن مؤقت dest، دون التحقق من طول haystacka. إذا ألقى المرء نظرة على الدالة المستدعية (العنوان 0x1CE6C)، يمكنه استنتاج أن حجم dest هو 256 بايت. وبما أن المهاجم يمكنه التحكم في محتوى CONTENT_TYPE، فيمكنه إرسال السلسلة 'boundary=' متبوعة بما لا يقل عن 257 حرفًا لاستغلال تجاوز سعة المخزن المؤقت (buffer overflow).
تم العثور على خطأين مشابهين آخرين في نفس عينة البرمجيات، يتعلقان بملفات تعريف الارتباط HTTP (HTTP cookie). أحدهما موضح أدناه:
v10 = getenv("HTTP_COOKIE");
if ( v10 )
{
strcpy((char *)&v5, &v10[v11]);
v17 = strlen((const char *)&v5);
}
هنا، يشير المتغير v10 إلى ملف تعريف ارتباط المستخدم، والذي يمكن أن يصل حجمه إلى 4 كيلوبايت على الأكثر (وفقًا لـ RFC2109). ومع ذلك، فإن المتغير v5 يبلغ حجمه 1024 بايت (كما يمكننا استنتاج ذلك من إطار مكدس الدالة). هذا يمكن أن يؤدي إلى تجاوز سعة المخزن المؤقت.
تم الإبلاغ عن هذه الأخطاء وتأكيدها من قبل D-Link.
تمثل عينات البرمجيات هذه بنية مشابهة لـ DIR-880L وتحتوي على نفس الأخطاب المتعلقة بنفس حقول HTTP.