
إعادة إنتاج وتحليل السبب الجذري لـ CVE-2023-32233، وهو ثغرة use-after-free في نواة Linux في nf_tables تتيح تصعيد الصلاحيات محليًا، مع PoC وملاحظات الاستغلال.
ما هو هذا المستودع: إعادة إنتاجي العملية ودراستي لـ CVE-2023-32233، وهو use-after-free في نظام Netfilter الفرعي nf_tables في نواة Linux يتيح تصعيد الصلاحيات محليًا، تم الكشف عنه علنًا في مايو 2023 بواسطة Patryk Sondej و Piotr Krysiuk.
الإسناد: الـ PoC (exploit.c) والتحليل الأصلي من إعداد
@Liuk3r. عملي في هذا المستودع
هو إعادة إنتاج الاستغلال في مختبري الخاص (Ubuntu 23.04، النواة 6.2.0-20)
وتوثيق السبب الجذري وسلسلة الاستغلال أدناه. تم إجراء جميع الاختبارات
على أجهزة مختبرية مخصصة.
تعالج nf_tables تحديثات الإعدادات كدفعة ذرية. التحقق من كل عملية مقابل تغيرات الحالة للعمليات السابقة في نفس الدفعة غير كافٍ. بشكل ملموس:
nft_rule يحتوي على تعبير lookup على nft_set مجهول
يحمل بعض العناصر.NFT_MSG_DELRULE — يحذف القاعدة، مما يحذف ضمنيًا تعبير
lookup و nft_set المجهول؛NFT_MSG_DELSETELEM — يحذف عنصرًا من المجموعة المجهولة
المحذوفة بالفعل.nf_tables_commit_release() الموارد في قائمة
nf_tables_destroy_list، وتُعالج لاحقًا بواسطة
nf_tables_trans_destroy_work():
أولًا nft_commit_release() → nf_tables_rule_destroy() →
nft_lookup_destroy() → nft_set_destroy() → kvfree() يحرر
nft_set؛
ثم، بالنسبة لـ NFT_MSG_DELSETELEM، يستدعي nf_tables_set_elem_destroy()
الدالة nft_set_elem_ext() التي تشير إلى nft_set المحرر:
إذا تم إفساد set->ops->elemsize، فسيتم تفسير موقع ذاكرة يختاره المهاجم
كـ nft_set_ext — وهي البدائية التي يُبنى عليها كل شيء آخر.
nf_tables_trans_destroy_work() التي تعمل على
خيط عامل في الخلفية: أدخل عملية تدمير مجموعة كبيرة كتأخير متحكم به،
واشغل وحدات المعالجة الأخرى، وأعد تخصيص قطعة nft_set المحررة
من نفس وحدة المعالجة بـ nft_set من نوع مختلف (بـ elemsize
مختلف) → ارتباك الأنواع.nft_set_ext مفسدة بإزاحات خارج النطاق بحيث
يمشي nf_tables_set_elem_destroy() عبر القطع المجاورة كقائمة من
nft_expr لتدميرها.nft_log بـ NFTA_LOG_PREFIX متحكم به؛
يحرر nft_log_destroy() الـ priv->prefix، مما يمنح بدائية تخصيص
متداخلة في kmalloc-{8..192} (محدودة بالبايت الصفري في البداية).nft_object->udata لرفع قيد البايت الصفري
على القراءة المعلقة.والجدير بالذكر أن البدائيات المختارة تتجنب أي شيء قد يعيقه CFI — لا حاجة لاختطاف استدعاء غير مباشر في أي خطوة.
SLAB_FREELIST_HARDENED)، و INIT_ON_FREE، وقيود إعادة استخدام
slab لكل وحدة معالجة — كلها تهاجم الخطوة 1؛ CFI (حيث يوجد) يقيد الخطوة 3+.nf_tables
التي تحتوي على DELRULE+DELSETELEM على مجموعات مجهولة؛ فرز الأعطال
لـ nft_set_elem_ext / nf_tables_trans_destroy_work في المكدس.nftables صلاحية CAP_NET_ADMIN، لكن
فضاءات أسماء المستخدمين غير المميزة تمنحها — لهذا السبب يُعد
kernel.unprivileged_userns_clone=0 مفتاح تقوية ذا معنى.تم الاختبار تحت Ubuntu 23.04 (Lunar Lobster)، النواة 6.2.0-20-generic.
sudo apt install gcc libmnl-dev libnftnl-dev
gcc -Wall -o exploit exploit.c -lmnl -lnftnl
يستهدف الملف التعريفي المدمج نوى Ubuntu 23.04 الثنائية
(linux-image-6.2.0-20-generic 6.2.0-20.20). لاختبار نوى أخرى،
استخرج الرموز إلى ملف profile:
modprobe nf_tables
egrep ' (nft_counter_ops|nft_counter_destroy|free_percpu|modprobe_path)(\s|$)' /proc/kallsyms > profile
يختلف تخطيط لغة الآلة لـ nft_counter_destroy() حسب المترجم
والخيارات؛ راجع ORIGIN.md للحصول على المرجع الكامل للمعاملات
(nft_counter_destroy_call_offset/mask/check) ومقابض ضبط السباق
(race_lead_sleep وغيرها). احتمالية النجاح المُبلّغ عنها ≥80% على أنظمة
Intel خاملة على العتاد الفعلي؛ بعض المعماريات الدقيقة (مثل Alder Lake) تحتاج
ضبطًا إضافيًا.
يترك الـ PoC النواة في حالة غير مستقرة بذاكرة مفسدة بعد تشغيل ناجح. اختبر فقط على نظام مخصص قابل للتخلص منه أو لقطة VM — لا تفعل ذلك أبدًا على أي شيء يحتوي على بيانات تهمك.
exploit.c — مصدر PoC (من @Liuk3r)ORIGIN.md — التحليل الأصلي للثغرة والاستغلال (من Liuk3r)README.md — هذا الملف: إعادة الإنتاج + ملاحظات تحليليأُجري البحث لأغراض دفاعية/تعليمية في بيئة مختبرية معزولة.
static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
void *elem)
{
return elem + set->ops->elemsize;
}
nft_dynset لنوعين من التعبيرات ذات الحالة:
nft_counter — يسرب nft_counter_ops → قاعدة nf_tables.ko
(يهزم KASLR للوحدة)؛nft_quota — مؤشر consumed يمنح قراءة عشوائية
(NFT_MSG_GETSETELEM → nft_quota_do_dump() → NFTA_QUOTA_CONSUMED)
وكتابة عشوائية (nft_overquota() تضيف skb->len إلى
*priv->consumed على حركة loopback).modprobe_path ("/sbin/modprobe" → "//tmp/modprobe") →
تنفيذ عملية بصلاحيات root بمحتوى يتحكم به المهاجم.