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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2019-8601 — استغلال ثغرة تم تصحيحها في JavaScriptCore | Kitploit
أدوات/GitHubGitHub/badaccess11/cve-2019-8601
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبالتعلم والتعليمتطوير الحمولاتاستغلال الملفات الثنائية
GitHubbadaccess11/cve-2019-8601

CVE-2019-8601

استغلال ثغرة تم تصحيحها في JavaScriptCore

عرض المستودع
1734منذ 6 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

استغلال CVE-2019-8601

هذا استغلال لثغرة أمنية في WebKit تم اكتشافها في الأصل بواسطة Fluoroacetate خلال مسابقة pwn2own في فانكوفر. على الرغم من أنني لم أكتشف هذه الثغرة، إلا أنني كتبت هذا الاستغلال لممارسة مهاراتي في تطوير الاستغلالات. المقال الأصلي حول هذا الاستغلال موجود هنا من Zero Day Initiative. على الرغم من أن هذا المقال جيد جدًا وكان مفيدًا في مساعدتي على فهم الثغرة، إلا أنه من وجهة نظر شخص يتحقق من الثغرة. لقد وجدت أن بعض التفاصيل الرئيسية مفقودة عند محاولة هندسة هذا الاستغلال من الصفر، وآمل في سد بعض الفجوات التي فاتتها مقال ZDI واكتساب مهارات عملية حول كيفية هندسة استغلال معقد من الصفر.

خطوات الاستغلال

تعمل هذه الخطوات كإطار عام للحصول على تنفيذ تعليمات برمجية تعسفي داخل JavaScriptCore (JSC)، محرك JavaScript لـ WebKit

  • تحديد الثغرة
  • تشغيل الثغرة وتعطل مع تفعيل ASAN
  • الحصول على بدائيات leakAddr و fakeObj
  • إفساد butterfly المصفوفة لتحقيق بدائيات القراءة والكتابة
  • استخدام بدائيات القراءة والكتابة لتحقيق تنفيذ تعليمات برمجية تعسفي داخل JSC

تحديد الثغرة

الثغرة التي سيتم استغلالها هي تجاوز سعة عدد صحيح يحدث في الكود الناتج عن مترجم DFG في الوقت المناسب (JIT) لـ WebKit. يحدث هذا تحديدًا في دالة compileNewArrayWithSpread. سيتم استدعاء هذه الدالة عندما يتم تحويل الكود الذي يستخدم صيغة الانتشار في JavaScript لإنشاء مصفوفة جديدة بواسطة DFG.

compileNewArrayWithSpread

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

compileAllocateNewArrayWithSize

ستقوم دالة compileAllocateNewArray بعد ذلك بتمرير الطول الذي تم حسابه سابقًا إلى emitAllocateButterfly.

emitAllocateButterfly

ستقوم دالة emitAllocateButterfly بعد ذلك بإزاحة الحجم إلى اليسار بمقدار 3 بتات، وهو ما يعادل ضربه في 8. ومع ذلك، لا يوجد فحص للتجاوز، وبالتالي يمكن لرقم مثل 0x20000001 أن يتجاوز إلى 0x8.

يوضح برنامج C هذا الثغرة:

overflow-example2

overflow-example

يمكننا استخدام هذه الثغرة لخداع محرك JavaScript ليعتقد أننا قمنا بتخصيص مصفوفة بحجم 0x20000001 ولكن في الواقع قمنا فقط بتخصيص مساحة كافية لـ JSValue واحد (8 بايت). سيؤدي ذلك إلى بدائية قراءة وكتابة خارج الحدود (OOB) يمكن بعد ذلك استغلالها لتحقيق قراءة وكتابة تعسفية وفي النهاية تنفيذ تعليمات برمجية عن بعد (RCE).

  • تحديد الثغرة

تشغيل الثغرة مع ASAN

لتأكيد أن لدينا قراءة خارج الحدود، سنحاول تشغيل هذه الثغرة على بناء مُعقّم العناوين (ASAN) لـ JSC.

لفعل ذلك من دليل WebKit، يمكننا تشغيل الأوامر:```bash Tools/Scripts/set-webkit-configuration --asan Tools/Scripts/build-jsc --jsc--only --debug

سيؤدي هذا إلى بناء نسخة تصحيح أخطاء من JSC مع تمكين ASAN مما يسمح لنا بالتحقق مما إذا كنا قد نجحنا في تشغيل الثغرة الأمنية أم لا.

إليك التكرار الأول لـ exploit.js```javascript
function jitMe(array){
  return [...array]
}

let dummy = [1.1]
for(let i = 0; i < 200; i++){
  jitMe(dummy);
}

let a = []

let len = 0x20000001                                                                     

for(let i = 0; i < len; i++){
  a[i] = 1.1 
}

jitMe(a)

عند تشغيل هذا أحصل على الخطأ التالي:

Program terminated with signal SIGKILL, Killed.
The program no longer exists.

كان تخميني أن الذاكرة تُستهلك بشكل كبير عند محاولة تخصيص مصفوفة بهذا الحجم. لتأكيد ذلك، أضفت نقطة توقف (breakpoint) إلى كود JITed عن طريق إضافة استدعاء لـ m_jit.breakpoint() داخل compileNewArrayWithSpread الذي يضيف تعليمة int3 إلى كود JITed.

بعد إضافة نقطة التوقف، وجدت أنها لم تُضرب، ثم قررت اختبار طول 0x20001. ثم أدركت أن الكود لم يكن يُجمَّع حتى، لذا أضفت المزيد من التكرارات لتفعيل DFG compiler.```javascript function jitMe(array){ for(let i = 0; i < 0x4000; i++){ let x = 1 + 1 } return [...array] }

let dummy = [1.1] for(let i = 0; i < 60; i++){ print(i) jitMe(dummy); }

let a = []

let len = 0x20000001

for(let i = 0; i < len; i++){ a[i] = 1.1 }

jitMe(a)

اختبار البرنامج كما هو لا يزال يؤدي إلى SIGKILL، ولكن عند الاختبار بطول أصغر، يتم ضرب نقطة التوقف. في هذه المرحلة، لا يزال يبدو لي أن JSC ينفد من الذاكرة عند محاولة معالجة تلك المصفوفة الضخمة.

للتعامل مع ذلك، قررت تخصيص مصفوفة `a` أصغر ثم استخدام بناء الجملة المنتشر (spread syntax) لاستخدامها عدة مرات عند إنشاء المصفوفة التالفة، مما أدى إلى ملف exploit.js التالي```
function jitMe(array){
  for(let i = 0; i < 0x4000; i++){
    let x = 1 + 1
  }
  return [...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array]
}

let dummy = [1.1]
for(let i = 0; i < 100; i++){
  print(i)
  jitMe(dummy);
}

let a = []

let len = 0x20000010 / 0x10

for(let i = 0; i < len; i++){
  a[i] = 1.1
}

jitMe(a)

باستخدام هذا الكود تمكنا من الوصول إلى نقطة التوقف دون SIGKILL! وكالمعتاد، يؤدي إصلاح مشكلة إلى ظهور أخرى، وقد حصلنا على SIGABORT بدلاً من ذلك... باستخدام الأمر bt في gdb نرى أنه تم استدعاء operationNewArrayWithSize والذي استدعى create.

backtrace1

يبدو غريباً أن الكود المُجمَّع في الوقت الحقيقي (JIT) الخاص بنا سوف يستدعي operationNewArrayWithSize، ولا بد أن الكود المُجمَّع اضطُر لسلوك مسار بطيء إلى محرك JavaScript لسبب ما.

slowcases

نلاحظ في compileAllocateNewArrayWithSize وجود خروج إلى operationNewArrayWithSize. بعد ذلك نحتاج إلى معرفة سبب الخروج بالضبط إلى الحالة البطيئة.

نرى في compileNewArrayWithSpread أن shouldConvertLargeSizeToArrayStorage مضبوطة على false وأن هذا المسار البطيء لن يكون موجوداً في الكود المُجمَّع.

compileNewArrayWithSpread2

لذلك من المنطقي أن المسار البطيء يتم الوصول إليه في مكان ما داخل emitAllocateJSObject.

emitAllocateJSObject

emitAllocateJSObject يستدعي emitAllocateJSCell والذي بدوره يستدعي emitAllocate.

emitAllocate

emitAllocateWithNonNullAllocator

بدون معرفة كيفية عمل مُخَصِّص WebKit، يبدو هذا مربكاً جداً. لذلك قررت إضافة نقاط توقف قليلة وتنفيذ الكود خطوة بخطوة في gdb.

بعد الوصول إلى نقطة توقف موضوعة في emitAllocateVariableSized والتي تم استدعاؤها بواسطة emitAllocateButterfly، نرى كود التجميع التالي:

assemblyEmitAllocateVariableSized

والذي يتوافق مع الكود الذي أرسله مُجمّع JIT هنا:

تنزيل الأداة