
تقرير تحليل CVE-2023-4911 (Looney Tunables) ومختبر إعادة إنتاج باستخدام Docker
| البند | الوصف |
|---|---|
| CVE ID | CVE-2023-4911 |
| نوع الهجوم | تجاوز سعة المخزن المؤقت في الكومة → تصعيد الامتيازات المحلية (Local Privilege Escalation) |
| CVSS 3.1 | 7.8 (مرتفع) |
| تاريخ الإفصاح | 2023-10-03 |
| نقطة الضعف | محلل GLIBC_TUNABLES في المُحمِّل الديناميكي لـ glibc (ld.so) |
| الإصدارات المتأثرة | glibc 2.34~2.38 |
CVE-2023-4911 هي ثغرة تجاوز سعة المخزن المؤقت في الكومة (heap buffer overflow) تظهر أثناء قيام المُحمِّل الديناميكي في مكتبة GNU C (glibc) بتحليل متغير البيئة GLIBC_TUNABLES. وباستغلال هذا التجاوز، يمكن للمهاجم التلاعب بمسار بحث المُحمِّل الديناميكي عن المكتبات (RPATH)، بحيث يُحمَّل عند تشغيل أي ثنائي SUID root (مثل su وsudo) مكتبة مشتركة خبيثة أعدّها المهاجم بدلاً من المكتبات الأصلية، ما يسمح له بتنفيذ تعليمات برمجية عشوائية بصلاحيات root. وبما أن glibc تمثل مكوّنًا أساسيًا في جميع توزيعات لينكس الرئيسية تقريبًا، فقد أثرت هذه الثغرة على معظم التوزيعات المبنية على glibc الصادرة بعد أبريل 2021.
while (true)
{
char *name = p;
size_t len = 0;
/* 이름(name) 길이 찾기 */
while (p[len] != '=' && p[len] != ':' && p[len] != '\0')
len++;
/* '=' 없이 끝나면 종료 */
if (p[len] == '\0')
{
if (__libc_enable_secure)
tunestr[off] = '\0';
return;
}
/* ':'를 먼저 만나면 잘못된 항목 */
if (p[len] == ':')
{
p += len + 1;
continue;
}
/* '='를 만났으므로 value 시작으로 이동 */
p += len + 1;
/* 원본 문자열에서 value 계산 */
char *value = &valstring[p - tunestr];
len = 0;
/* value 길이 찾기 */
while (p[len] != ':' && p[len] != '\0')
len++;
...
/* tunestr에 복사 */
...
if (p[len] != '\0')
p += len + 1;
}
__tunables_init() عن GLIBC_TUNABLES في قائمة متغيرات البيئة.tunables_strdup() مخزنًا مؤقتًا عبر __minimal_malloc() وينسخ السلسلة الأصلية (في هذه المرحلة تكون malloc تطبيقًا مبكرًا جدًا لم يُهيّأ بالكامل بعد).parse_tunables() في هذا المخزن وفقًا للنقطتين (:) وتفصل كل زوج key=value، ثم تُسند القيمة إلى المُعدِّل (tunable) المقابل.تعالج parse_tunables() كل مُعدِّل وفق الترتيب التالي: تحليل الاسم → تحريك p → تحليل القيمة → تحريك p. في المدخلات الطبيعية، يتحرك p بعد معالجة القيمة بالكامل إلى بداية المُعدِّل التالي لتحليله.
لكن إذا كان الإدخال على الشكل التالي name=name=value:
GLIBC_TUNABLES=glibc.malloc.mxfast=glibc.malloc.mxfast=AAAA...(긴 문자열)
في عملية التحليل الأولى، يُعتبر النص glibc.malloc.mxfast=AAAA... بأكمله قيمة واحدة ويُنسخ إلى المخزن المؤقت tunestr. وبعد ذلك، ولعدم وجود النقطتين (:) اللتين تفصلان المُعدِّل التالي بعد هذه القيمة، لا يتمكن مؤشر التحليل (p) من الانتقال إلى العنصر التالي، بل يعود ليشير إلى موضع بداية القيمة المنسوخة.
المشكلة أن هذه القيمة نفسها تحمل صيغة name=value. في التكرار التالي، يعتقد المحلل خطأً أنها مُعدِّل جديد، فيسجّل بيانات مكررة في المخزن المؤقت. وبما أن tunestr مُخصص بحجم السلسلة الأصلية فقط، فإن البيانات المكررة تتجاوز حدود المخزن المؤقت، ما يؤدي إلى تجاوز سعة في الكومة.
يقوم تجاوز سعة المخزن المؤقت في الكومة بالكتابة فوق منطقة الكومة المجاورة التي خصصتها __minimal_malloc() بشكل متتابع. ويستغل المهاجم ذلك لتغيير المؤشر l_info[DT_RPATH] في البنية الداخلية link_map الخاصة بالمُحمِّل الديناميكي (ld.so) إلى عنوان في المكدس يتحكم فيه المهاجم.
وفي منطقة المكدس هذه توجد بنية Elf64_Dyn مُعدّة مسبقًا، تحدد دليلًا يختاره المهاجم كمسار جديد للبحث عن المكتبات (RPATH). ونتيجة لذلك، يقوم ld.so بتحميل المكتبة المشتركة التي أعدّها المهاجم بالدرجة الأولى بدلاً من مكتبات النظام الأصلية.
GLIBC_TUNABLES بصيغة name=name=value.su) بصلاحيات مستخدم عادي.parse_tunables() الخاصة بـ ld.so.l_info[DT_RPATH] في link_map إلى عنوان في المكدس توجد فيه بنية Elf64_Dyn المُزيّفة التي أعدّها.libc.so.6 الخبيث الذي أعدّه المهاجم باستخدام معلومات RPATH المعدّلة.libc.so.6 الخبيث بصلاحيات root، بما في ذلك setuid(0) وsetgid(0) وتشغيل /bin/sh.يستخدم إثبات المفهوم (PoC) أسلوب القوة العمياء (brute force) عبر تكرار استدعاء execve() حتى يتشكّل تخطيط الذاكرة المطلوب تحت تأثير التوزيع العشوائي (ASLR). لذلك، قد يختلف نجاح الهجوم والوقت المستغرق حسب البيئة، ويتطلب الأمر عادةً من مئات إلى آلاف المحاولات المتكررة.
أولاً، استنسخ (clone) المحتوى من git إلى الدليل.
git clone https://github.com/baeseungwon1010/CVE-2023-4911

ابنِ صورة Docker باستخدام الأمر التالي.
cd C* && docker compose run --rm cve-2023-4911-lab

بعد الدخول إلى الحاوية، نفّذ كود الاستغلال (exploit).
cd /home/student/exploit && ./exp
بعد التشغيل والانتظار، ستلاحظ التحول من مستخدم عادي إلى sudo(0).

حدّث glibc من الإصدارات المتأثرة إلى إصدارات أحدث (مُصحَّحة). بعد التحديث، أعد الإقلاع/إعادة التشغيل إن أمكن لضمان عدم بقاء النسخة القديمة من glibc في الذاكرة. وفي حال تعذّر التحديث الفوري، يمكن اتخاذ إجراء مؤقت يتمثل في إزالة العمليات غير الضرورية التي تحمل SUID أو SGID.
su، يحصل المهاجم على قشرة (shell) بصلاحيات root دون التحقق من كلمة المرور.