Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
cve-2023-5217-poc — PoC لتشغيل CVE-2023-5217 من واجهة WebCodecs أو MediaRecorder في المتصفح. | Kitploit
أدوات/GitHubGitHub/ut-security/cve-2023-5217-poc
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبالاختبار العشوائيالتعلم والتعليماستغلال الملفات الثنائية
GitHubut-security/cve-2023-5217-poc

cve-2023-5217-poc

PoC لتشغيل CVE-2023-5217 من واجهة WebCodecs أو MediaRecorder في المتصفح.

عرض المستودع
1631منذ 2 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2023-5217: إثبات مفهوم تجاوز سعة الكومة لترميز VP8 في libvpx

CVE-2023-5217 هي ثغرة في libvpx تم استغلالها في البرية وتم العثور عليها بواسطة Clément Lecigne من فريق تحليل التهديدات في Google لتستهدف Chrome.

يُظهر هذا المستودع كيفية تشغيل CVE-2023-5217 في المتصفح باستخدام واجهات برمجة التطبيقات WebCodecs و MediaRecorder. تسمح CVE-2023-5217 بتجاوز سعة المخزن المؤقت للكومة بطول تجاوز مسيطر عليه وكتابة فوقية لقيمة صغيرة مكررة من 4 بايتات. ليس معروفًا حاليًا كيف تم استغلال CVE-2023-5217 في البرية.

في وقت الإفصاح العام، كان هناك تصحيحان في libvpx وواحد في Chromium عالجوا CVE-2023-5217. تضمنت تصحيحات libvpx تعطيل تغييرات عدد خيوط VP8 و اختبار للترميز متعدد الخيوط. قام تصحيح Chromium بتعطيل تعديل عدد الخيوط في WebCodecs.

المشكلة الأساسية في libvpx الإصدار 1.13.0 Ugly Duckling

ملخص

libvpx هي مكتبة تتعامل مع ترميز وفك ترميز VP8/VP9.

المشكلة الرئيسية في CVE-2023-5217 هي أن تقليل عدد الخيوط مع زيادة ارتفاع الإطار في جلسة ترميز VP8 في libvpx يؤدي إلى تجاوز سعة كومة خطي بطول مسيطر عليه وكتابة فوقية مسيطر عليها لقيمة صغيرة مكررة من 4 بايتات. الفرق في ارتفاع الإطار يتحكم في طول الكتابة الفوقية، وعرض الإطار الجديد يتحكم في قيمة الـ 4 بايتات التي تُكتب بشكل متكرر. يمكن استغلال هذه الثغرة عدة مرات لكتابة قيم مختلفة من 4 بايتات بشكل مستمر عن طريق تقليل الارتفاع في كل إعداد لاحق.

تفاصيل

يحافظ مُشفر VP8 في libvpx على مصفوفة تسمى mt_current_mb_col تخزن العمود الحالي الذي يعمل عليه خيط الترميز. يتم تخصيص هذه المصفوفة فقط إذا كان هناك أكثر من خيط واحد، وحجمها هو دالة في mb_rows، حيث mb_rows = height_of_frame >> 4 ويتم تقريب frame_height لأعلى إلى أقرب مضاعف للعدد 16.

root@kitploit:~
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/common/alloccommon.c#L85
// The width and height are rounded up to a multiple of 16 and then assigned to `mb_rows` and `mb_cols`
int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height) {
    ...
    // Round up the width/height up to the nearest multiple of 16
    if ((width & 0xf) != 0) width += 16 - (width & 0xf);
    if ((height & 0xf) != 0) height += 16 - (height & 0xf);
    ...
    oci->mb_rows = height >> 4;
    oci->mb_cols = width >> 4;
    ...
}
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/onyx_if.c#L1232
// This snippet shows the allocation of `mt_current_mb_col`
void vp8_alloc_compressor_data(VP8_COMP *cpi) {
  ...
  // Only allocate if we have more than 1 thread
  if (cpi->oxcf.multi_threaded > 1) {
    int i;

    vpx_free(cpi->mt_current_mb_col);
    // sizeof(*cpi->mt_current_mb_col) is 4
    CHECK_MEM_ERROR(&cpi->common.error, cpi->mt_current_mb_col,
                    vpx_malloc(sizeof(*cpi->mt_current_mb_col) * cm->mb_rows));
    for (i = 0; i < cm->mb_rows; ++i)
      vpx_atomic_init(&cpi->mt_current_mb_col[i], 0);
  }
  ...
}

بمجرد أن ينتهي libvpx من ترميز إطار، فإنه يخزن عدد الأعمدة المُرمزة بالإضافة إلى mt_sync_range في mt_current_mb_col.

root@kitploit:~
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/onyx_if.c#L1212
// Snippet where the mt_sync_range value is set, based on the width.
void vp8_alloc_compressor_data(VP8_COMP *cpi) {
    ...
#if CONFIG_MULTITHREAD
  if (width < 640) {
    cpi->mt_sync_range = 1;
  } else if (width <= 1280) {
    cpi->mt_sync_range = 4;
  } else if (width <= 2560) {
    cpi->mt_sync_range = 8;
  } else {
    cpi->mt_sync_range = 16;
  }
#endif
  ...
}
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/encodeframe.c#L560
// Function where the attacker chosen value is written
static void encode_mb_row(...) {
  ...
  const int nsync = cpi->mt_sync_range; // This value is set in vp8_alloc_compressor_data
  vpx_atomic_int rightmost_col = VPX_ATOMIC_INIT(cm->mb_cols + nsync);
  ...
  if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {
    current_mb_col = &cpi->mt_current_mb_col[mb_row];
  }
  ...
  if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {
    // current_mb_col is a reference to mt_current_mb_col
    vpx_atomic_store_release(current_mb_col,
                             vpx_atomic_load_acquire(&rightmost_col));
  }
  ...
}

لتجاوز mt_current_mb_col، نحتاج إلى ثلاثة إعدادات ترميز:

  1. configinit: أثناء التهيئة، يقوم libvpx بتعيين initial_width و initial_height. هذه هي الحدود القصوى الممكنة للإعدادات اللاحقة. عدد الخيوط هنا لا يهم. نحتاج إلى الإعداد الوسيط لأنه لا يمكن أن تكون أي مجموعة عرض/ارتفاع لاحقة أكبر مما بدأنا به.
  2. configvuln: أثناء إعادة التهيئة، إذا تم استخدام أكثر من خيط واحد، يقوم libvpx بإنشاء تخصيص mt_current_mb_col الضعيف بناءً على configvuln.height. يجب أن يكون هذا الارتفاع الجديد أصغر من configinit.initial_height وإلا سنحصل على خطأ.
  3. configattack: أثناء إعادة التهيئة، إذا تم استخدام خيط واحد فقط، فلن يقوم libvpx بإعادة تخصيص mt_current_mb_col مما يتركه في حالة ضعيفة. سيقوم libvpx بكتابة القيمة (configattack.width >> 4) + 1 (حيث 1 هو المتغير mt_sync_range ويتم تقريب العرض لأعلى إلى أقرب مضاعف للعدد 16) خارج الحدود المخصصة سابقًا عندما يتحقق الشرط التالي:
root@kitploit:~
\text{ceil}(\text{config}_{\text{init}}.\text{height}/16) \geq \text{ceil}(\text{config}_{\text{attack}}.\text{height}/16) \gt \text{ceil}(\text{config}_{\text{vuln}}.\text{height}/16)$$

فيضان mt_current_mb_col

بشكل أكثر تحديدًا، لنفترض أننا قمنا بتهيئة إعداد ترميز VP8 باستخدام configinit مع width = 1200، height = 1200، threads = 4. الهجوم كالتالي:

  1. يقوم configvuln بإعادة تهيئة المشفر بـ width = 500 (512 بعد التقريب لأعلى)، height = 700 (704 بعد التقريب لأعلى)، و threads = 2. يتم تعيين المتغير mb_rows إلى 704/16 = 44، ويتم تخصيص المصفوفة mt_current_mb_col إلى (44)*4 = 176 بايت. القيمة المخزنة في mt_current_mb_col هي 512/16 + 1 = 33.
  2. يقوم configattack بإعادة تهيئة المشفر بـ width = 18 (32 بعد التقريب لأعلى)، height = 1000 (1008 بعد التقريب لأعلى)، و threads = 1. نظرًا لأن mt_current_mb_col يتم إعادة تخصيصها فقط عندما يكون هناك أكثر من خيط واحد، فإنها تبقى بنفس الحجم، ومع ذلك فإن mb_rows الآن مضبوط على 1008/16 = 63. عندما يستدعي libvpx encode_mb_row، فإنه سيكتب فوق (63-44)*4 = 68 بايت بعد تخصيص mt_current_mb_col، ويكتب بشكل متكرر القيمة 32/16 + 1 = 3، حيث 32 هو العرض بعد التقريب لأعلى، و 1 هو قيمة mt_sync_range.
  3. يمكن للمهاجم إعادة استغلال هذه الثغرة بارتفاع أصغر من ذلك الموجود في configattack ولكن لا يزال أكبر من configvuln لكتابة قيمة أخرى. على سبيل المثال، يمكن للمهاجم إنشاء configattack' بـ width = 34 و height = 990، وتعيين mb_rows = 992/16 = 62 و mb_cols = 48/16 = 3، وبذلك يكتب فقط (62-44)*4 = 64 بايت بعد التخصيص الأصلي بالقيمة 4.

الاستغلال

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

root@kitploit:~
// https://github.com/webmproject/libvpx/blob/67bfb41ed8598edfb25bd6f245f9c39a68808548/vp8/vp8_cx_iface.c#L301
static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
 ...
  oxcf->multi_threaded = cfg.g_threads;

Firefox

في فايرفوكس، يمكننا التحكم في عدد الخيوط عن طريق تعديل مساحة الإطار التي نرمزها في VP8TrackEncoder. إذا كانت مساحة الإطار أكبر من 307,200 (إطار 640x480) وكان الجهاز يحتوي على أكثر من نواتين، فسيتم استخدام أكثر من خيط واحد.

root@kitploit:~
// https://searchfox.org/mozilla-central/source/dom/media/encoder/VP8TrackEncoder.cpp#97
nsresult CreateEncoderConfig(...) {
  ...
  int32_t number_of_cores = PR_GetNumberOfProcessors();
  if (aWidth * aHeight > 1920 * 1080 && number_of_cores >= 8) {
    config->g_threads = 4;  // 4 threads for > 1080p.
  } else if (aWidth * aHeight > 1280 * 960 && number_of_cores >= 6) {
    config->g_threads = 3;  // 3 threads for 1080p.
  } else if (aWidth * aHeight > 640 * 480 && number_of_cores >= 3) {
    config->g_threads = 2;  // 2 threads for qHD/HD.
  } else {
    config->g_threads = 1;  // 1 thread for VGA or less
  }
  ...

وجدنا أن واجهة برمجة تطبيقات MediaRecorder تعتمد على VP8TrackEncoder، ويمكننا تعديل العرض والارتفاع عن طريق تغيير حجم اللوحة القماشية التي يتم تسجيلها. انظر قسم MediaRecorder أدناه لمعرفة كيفية استدعاء هذا.

Chrome

يقوم Chrome أيضًا بتعديل عدد الخيوط بناءً على مساحة الإطار الجاري ترميزها، معدلة حسب عدد النوى.

root@kitploit:~
// https://source.chromium.org/chromium/chromium/src/+/main:media/video/vpx_video_encoder.cc;l=84
EncoderStatus SetUpVpxConfig(...) {
  ...
  // Set the number of threads based on the image width and num of cores.
  config->g_threads = GetNumberOfThreadsForSoftwareEncoding(opts.frame_size);
}

// https://source.chromium.org/chromium/chromium/src/+/main:media/base/video_encoder.cc;drc=f5bdc89c7395ed24f1b8d196a3bdd6232d5bf771;l=33
int GetNumberOfThreadsForSoftwareEncoding(gfx::Size frame_size) {
  int area = frame_size.GetCheckedArea().ValueOrDefault(1);
  // Default to 1 thread for less than VGA.
  int desired_threads = 1;

  if (area >= 3840 * 2160) {
    desired_threads = 16;
  } else if (area >= 2560 * 1080) {
    desired_threads = 8;
  } else if (area >= 1280 * 720) {
    desired_threads = 4;
  } else if (area >= 640 * 480) {
    desired_threads = 2;
  }

  // Clamp to the number of available logical processors/cores.
  desired_threads =
      std::min(desired_threads, base::SysInfo::NumberOfProcessors());

  return desired_threads;
}

يتم استخدام هذا المسار بواسطة واجهة برمجة تطبيقات WebCodecs VideoEncoding، حيث يمكننا تعديل عرض/ارتفاع الترميز مباشرة. انظر قسم WebCodecs لرؤية كيفية عمل ذلك.

MediaRecorder

يظهر الملف mediarecorder.html كيفية إنشاء جلسة MediaRecorder من لوحة رسم وتعديل العرض والارتفاع لتشغيل إعادة تكوين ترميز VP8 لتشغيل CVE-2023-5217 في متصفح ضعيف. عند تعديل معلمات عرض وارتفاع اللوحة القماشية، نستخدم setTimeout لضمان أن جلسة ترميز VP8 لديها وقت كافٍ لإعادة التهيئة. يمكن تعديل معلمة timeout لتحسين الموثوقية.

الحالة

  • ✅ فايرفوكس: يؤدي إلى تعطل في معالج العرض لفايرفوكس.
  • ❌ متصفحات Chromium: لا تغير المتصفحات المبنية على Chromium عدد الخيوط عند إعادة تكوين المشفر في جلسة MediaRecorder [كود].
  • ❌ سفاري: لا يدعم WebKit VP8 لجلسات MediaRecorder [كود].

عرض فايرفوكس

لاختبار على فايرفوكس، يمكنك استخدام fuzzfetch للحصول على بناء ASAN قبل أن يتم تصحيح هذه الثغرة باستخدام الأمر fuzzfetch --build 2023-09-27 -a ثم افتح mediarecorder.html مباشرة.

عرض فايرفوكس

WebCodecs

تظهر الملفات webcodecs.html و webcodecs.js كيفية استخدام واجهة برمجة تطبيقات WebCodecs في Worker لتشغيل CVE-2023-5217 في متصفح ضعيف. لدينا تحكم أكبر في استدعاءات ترميز إطار في WebCodecs مقارنة بـ MediaRecorder، لكننا لا نزال نعتمد على مهلة زمنية لتغيير وتنفيذ كل من الخطوات الثلاث.

الحالة

  • ✅ متصفحات Chromium: يؤدي إلى تعطل علامة التبويب. تم تضمين تصحيح Chromium هذا لـ WebCodecs في التقييم الأولي.
  • ❌ فايرفوكس: لا يدعم فايرفوكس ترميز WebCodecs (فك الترميز مفعل خلف علامة إعداد).
  • 🚧 سفاري: يدعم سفاري ترميز WebCodecs، لكنني لم أتمكن من الحصول على أي تعطلات.

عرض Chromium

لاختبار على Chromium، يمكنك استخدام get_asan_chrome.py للحصول على نسخة ضعيفة من Chrome باستخدام الأمر python get_asan_chrome.py --version 117.0.5938.131. ستحتاج بعد ذلك إلى بدء خادم HTTP محلي مع SSL. انظر gen_server_key.sh و server.py لإنشاء مفتاح خادم وبدء خادم. ثم يمكنك فقط فتح الصفحة في Chromium الضعيف لرؤية النتيجة.

عرض Chromium

WebCodecs + MediaRecorder مجتمعين

انظر combined.html الذي يستخدم MediaRecorder كخيار احتياطي عندما لا يتم العثور على WebCodecs. سيتم استخدام هذا الملف المدمج لاستهداف كل من Chrome و Firefox بنفس الصفحة.

الخاتمة

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

شكرًا للقراءة! المساهمات مرحب بها. لا تتردد في فتح Issue أو PR مع أي رؤى أخرى. ما تبقى لاستكشافه هو رؤية كيف يمكن أن تؤدي هذه الكتابة الفوقية الصغيرة المكونة من 4 بايتات إلى تنفيذ كود.

شكرًا لـ Anand Balaji على الملاحظات حول مسودة سابقة.

تنزيل الأداة