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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-8389 — تحليل فني واستغلال لإثبات المفهوم لـ CVE-2026-8389، وهي ثغرة ارتباك نوع في SpiderMonkey BaselineJIT في Firefox، تم توضيحها باستخدام اقتطاع البايت كود والتلاعب في فك الاستثناءات. | Kitploit
أدوات/GitHubGitHub/crixpwn/cve-2026-8389
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبCTFالتعلم والتعليماستغلال الملفات الثنائية
GitHubcrixpwn/cve-2026-8389

CVE-2026-8389

تحليل فني واستغلال لإثبات المفهوم لـ CVE-2026-8389، وهي ثغرة ارتباك نوع في SpiderMonkey BaselineJIT في Firefox، تم توضيحها باستخدام اقتطاع البايت كود والتلاعب في فك الاستثناءات.

عرض المستودع
407منذ 2 أشهرتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2026-8389

كان من المقرر استخدام هذه الثغرة في مسابقة Pwn2Own 2026 Berlin، ولكن تم إصلاحها في الإصدار 150.0.3.

اقتطاع حقل pcOffset في SpiderMonkey BaselineJIT على مسار التجميع الأساسي غير المتزامن خارج الخيط الرئيسي، مما يؤدي إلى تعليمات بايت كود داخل النطاق ولكن خاطئة أثناء فك الاستثناء وما يتبعه من خلط في الأنواع.

الملخص

يخزن RetAddrEntry إزاحة البايت كود pcOffset_ كحقل بت 28 بت. الثابت BaselineMaxScriptLength = 0x0fffffff المعرف في نفس الرأس مصمم ليتطابق تمامًا مع نطاق حقل البت ذلك.

root@kitploit:~
// js/src/jit/BaselineJIT.h:73
static constexpr uint32_t BaselineMaxScriptLength = 0x0fffffffu;

// js/src/jit/BaselineJIT.h:100-105
class RetAddrEntry {
  // Offset from the start of the JIT code where call instruction is.
  uint32_t returnOffset_;

  // The offset of this bytecode op within the JSScript.
  uint32_t pcOffset_ : 28;
root@kitploit:~
// js/src/jit/BaselineJIT.h:141-156 (RetAddrEntry constructor)
RetAddrEntry(uint32_t pcOffset, Kind kind, CodeOffset retOffset)
    : returnOffset_(uint32_t(retOffset.offset())),
      pcOffset_(pcOffset),
      kind_(uint32_t(kind)) {
  MOZ_ASSERT(returnOffset_ == retOffset.offset(),
             "retOffset must fit in returnOffset_");

  // The pc offset must fit in at least 28 bits, since we shave off 4 for
  // the Kind enum.
  MOZ_ASSERT(pcOffset_ == pcOffset);
  static_assert(BaselineMaxScriptLength <= (1u << 28) - 1);
  MOZ_ASSERT(pcOffset <= BaselineMaxScriptLength);

  MOZ_ASSERT(kind < Kind::Invalid);
  MOZ_ASSERT(this->kind() == kind, "kind must fit in kind_ bit field");
}

قبل الإصلاح، كان هذا الحد الأعلى يُفرض في إصدارات الإنتاج فقط داخل CanEnterBaselineJIT (js/src/jit/BaselineJIT.cpp)، وهو مسار الدخول الرئيسي للإحماء / OSR. مسار التجميع الأساسي غير المتزامن خارج الخيط الرئيسي لم يمر عبر هذا الفحص، لذا فإن السكريبت الذي يتجاوز حجم بايت كوده 256 ميجابايت يمكنه مسح التجميع الأساسي بينما يتم اقتطاع حقل pcOffset بصمت بواسطة تخزين 28 بت (pcOffset & 0x0FFFFFFF). MOZ_ASSERT الإعلاميان أعلاه (pcOffset_ == pcOffset و pcOffset <= BaselineMaxScriptLength) لا يفعلان شيئًا في إصدارات الإنتاج، لذا لم يتم اكتشاف الاقتطاع.

المسار المتأثر

مسار التجميع الأساسي غير المتزامن خارج الخيط الرئيسي:

root@kitploit:~
CompilationStencil::instantiateStencils
  -> MaybeDoEagerBaselineCompilations        (js/src/frontend/Stencil.cpp:2720)
    -> DispatchOffThreadBaselineBatchEager    (js/src/jit/BaselineJIT.cpp:386)
      -> BaselineCompileTask::runTask         (js/src/jit/BaselineCompileTask.cpp:69)
        -> BaselineCompile

قبل التصحيح، كان MaybeDoEagerBaselineCompilations يُفحص فقط script->baselineDisabled() و jit::CanBaselineInterpretScript(script). لا يتحقق أي منهما من طول السكريبت، لذا يمكن لسكريبت طويل جدًا الوصول إلى التجميع الأساسي عبر هذا المسار.

root@kitploit:~
// js/src/frontend/Stencil.cpp, MaybeDoEagerBaselineCompilations (pre-patch)
    if (script->baselineDisabled()) {
      continue;
    }

    if (!jit::CanBaselineInterpretScript(script)) {
      continue;
    }

على النقيض، كان مسار الخيط الرئيسي يفرض الحد (تم نقل هذه الكتلة لاحقًا إلى CanBaselineCompileScript المشتركة):

root@kitploit:~
// js/src/jit/BaselineJIT.cpp, CanEnterBaselineJIT (pre-patch)
  if (script->length() > BaselineMaxScriptLength) {
    script->disableBaselineCompile();
    return Method_CantCompile;
  }

النتيجة

يتم تحويل pcOffset المقتطع مرة أخرى إلى مؤشر بايت كود في JSJitFrameIter::baselineScriptAndPc، عبر RetAddrEntry::pc -> JSScript::offsetToPC.

root@kitploit:~
// js/src/jit/JSJitFrameIter.cpp:155-160
  // address.
  uint8_t* retAddr = resumePCinCurrentFrame();
  const RetAddrEntry& entry =
      script->baselineScript()->retAddrEntryFromReturnAddress(retAddr);
  *pcRes = entry.pc(script);
}
root@kitploit:~
// js/src/jit/BaselineJIT.h:162-164 (RetAddrEntry::pc)
jsbytecode* pc(JSScript* script) const {
  return script->offsetToPC(pcOffset_);
}

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

root@kitploit:~
// js/src/jit/JitFrames.cpp:584-591
static void HandleExceptionBaseline(JSContext* cx, JSJitFrameIter& frame,
                                    CommonFrameLayout* prevFrame,
                                    ResumeFromException* rfe) {
  MOZ_ASSERT(frame.isBaselineJS());
  MOZ_ASSERT(prevFrame);

  jsbytecode* pc;
  frame.baselineScriptAndPc(nullptr, &pc);

يقود هذا الـ pc الخاطئ إلى مطابقة غير صحيحة لملاحظات try أثناء فك الاستثناء (HandleExceptionBaseline يعتمد على script->trynotes())، مما يؤدي إلى قراءة خاطئة لفتحة المكدس. يمكن بعد ذلك معاملة فتحة ليست من نوع JSObject* كأنها كذلك وإرسالها عبر جدولها الافتراضي، مما ينتج عنه خلط في الأنواع يشكل الأساس لمزيد من الاستغلال.

تنزيل الأداة