分散式訓練攻擊面
專家4 分鐘閱讀更新於 2026-03-13
多 GPU、多節點 LLM 訓練中的安全漏洞:梯度共享攻擊、parameter server 入侵、內部威脅,以及基礎設施層級的訓練攻擊。
訓練大型語言模型需將運算分散於大量 GPU 與節點上。此分散製造了通訊通道——梯度交換、激活傳輸、參數同步——這些是單裝置訓練所沒有的攻擊面。遭入侵的訓練節點、位於梯度通訊通道上的中間人,或具惡意的基礎設施維運者,皆可以能於部署後仍留存的方式影響所訓練的模型。
分散式訓練架構
| 平行化類型 | 分散的對象 | 通訊模式 | 攻擊面 |
|---|---|---|---|
| 資料平行 | 訓練資料 | 每步後 all-reduce 梯度 | 梯度操弄 |
| 模型/張量平行 | 模型層/權重 | 層間激活張量 | 激活注入 |
| 管線平行 | 連續層群組 | 管線階段間激活 | 階段入侵 |
| 專家平行(MoE) | 專家子網路 | 路由決策 + 專家輸出 | 專家投毒 |
| ZeRO(第 1–3 階段) | Optimizer / 梯度 / 參數狀態 | 分片參數聚集 | 分片操弄 |
攻擊向量 1:梯度操弄
在資料平行訓練中,每個節點於本地批次上計算梯度並透過 all-reduce 共享。遭入侵的節點可注入對抗梯度:
# 正常分散式訓練步驟
def honest_training_step(model, batch, optimizer):
loss = model(batch).loss
loss.backward()
# All-reduce:於所有節點取梯度平均
for param in model.parameters():
dist.all_reduce(param.grad, op=dist.ReduceOp.AVG)
optimizer.step()
# 遭入侵節點:於 all-reduce 前修改梯度
def malicious_training_step(model, batch, optimizer, target_gradient):
loss = model(batch).loss
loss.backward()
# 以對抗梯度取代誠實梯度
for name, param in model.named_parameters():
if name in target_gradient:
# 將誠實梯度與對抗梯度混合
param.grad = (0.3 * param.grad +
0.7 * target_gradient[name].to(param.device))
# All-reduce 會將此與誠實節點的梯度平均
for param in model.parameters():
dist.all_reduce(param.grad, op=dist.ReduceOp.AVG)
optimizer.step()影響分析
| 被入侵節點 | 對訓練的效應 | 偵測難度 |
|---|---|---|
| 64 中的 1 個 | 梯度被稀釋 63 倍——微妙、緩慢的投毒 | 非常困難 |
| 8 中的 1 個 | 12.5% 的梯度影響——多步後可察覺 | 困難 |
| 8 中的 4 個 | 50% 的梯度影響——主導控制 | 中等(損失異常) |
攻擊向量 2:Parameter Server 入侵
在 parameter server 架構(對 LLM 較少見,但部分框架使用)中,中央伺服器彙整梯度並散布更新過的參數:
┌──────────┐ 梯度 ┌──────────────────┐ 參數 ┌──────────┐
│ Worker 1 │ ───────────▶ │ Parameter Server │ ───────────▶ │ Worker 1 │
│ Worker 2 │ ───────────▶ │ (已入侵) │ ───────────▶ │ Worker 2 │
│ Worker 3 │ ───────────▶ │ 於廣播前修改參數 │ ───────────▶ │ Worker 3 │
└──────────┘ └──────────────────┘ └──────────┘遭入侵的 parameter server 擁有完整控制:
- 梯度過濾 —— 丟棄改善安全行為的梯度
- 參數注入 —— 於廣播前修改特定權重值
- 選擇性更新 —— 對不同 worker 套用不同更新(造成發散)
- Checkpoint 操弄 —— 竄改已儲存的 checkpoint
攻擊向量 3:通訊通道攻擊
節點間梯度與激活通訊通常使用 NCCL(NVIDIA Collective Communication Library)於 InfiniBand 或 RoCE 上:
梯度通訊的中間人攻擊
| 通訊協定 | 加密 | MITM 風險 |
|---|---|---|
| NCCL on InfiniBand | 預設無 | 高——明文傳輸梯度 |
| NCCL on RoCE(Ethernet) | 預設無 | 高——標準網路攔截 |
| NCCL with SHARP(in-network reduction) | 無 | 高——交換器層級攔截 |
| gRPC(部分框架) | TLS 可選 | 中——視組態而定 |
# NCCL all-reduce 預設未加密
# 網路上的攻擊者可於送出與接收之間攔截並修改梯度
# 範例:不啟用加密的 NCCL 設定(常見預設)
import torch.distributed as dist
dist.init_process_group(
backend="nccl",
init_method="tcp://master:29500", # 未加密 TCP
rank=rank,
world_size=world_size,
)
# 後續所有 all-reduce 皆未加密攻擊向量 4:內部威脅
訓練基礎設施的內部人員所具備的存取權,是外部攻擊者無法複製的:
| 內部角色 | 存取 | 攻擊能力 |
|---|---|---|
| ML 工程師 | 訓練腳本、組態、資料管線 | 修改訓練程式、注入被投毒資料 |
| 基礎設施/DevOps | GPU 叢集、網路、儲存 | 入侵通訊、修改 checkpoint |
| 資料工程師 | 訓練資料管線、前處理 | 大規模資料投毒 |
| 模型審查者 | Checkpoint、評估管線 | 竄改評估以隱藏後門 |
Checkpoint 竄改
# 內部人員於部署前修改已儲存 checkpoint
import torch
def tamper_checkpoint(checkpoint_path, modifications):
"""修改已儲存 checkpoint 的特定權重。
需要對 checkpoint 儲存的寫入權限。"""
state_dict = torch.load(checkpoint_path)
for layer_name, new_values in modifications.items():
if layer_name in state_dict:
state_dict[layer_name] = new_values
# 覆寫原本 checkpoint
torch.save(state_dict, checkpoint_path)
# 若有使用 checksum,需重新計算並更新防禦框架
訓練完整性驗證
梯度 checksum
於 all-reduce 前後計算並驗證梯度張量的 checksum。偵測傳輸中的竄改。
梯度統計監控
追蹤各節點梯度統計(範數、方向、變異量)。標記梯度持續偏離分布的節點。
Checkpoint 來源追蹤
於建立時以密碼學簽章 checkpoint。部署前驗證簽章。維持所有 checkpoint 操作的僅可附加日誌。
通訊加密
對 gRPC 為基礎的框架啟用 TLS。對 NCCL,於基礎設施層使用加密網路架構(IPsec、WireGuard)。
存取控制與稽核
對訓練基礎設施存取採最小權限原則。對所有訓練操作進行完整稽核日誌。
| 防禦 | 防護對象 | 成本 |
|---|---|---|
| 梯度 checksum | 通訊 MITM | 約 5% 開銷 |
| 每節點梯度監控 | 遭入侵 worker | 監控基礎設施 |
| Checkpoint 簽章 | Checkpoint 竄改 | PKI 建置 |
| 網路加密 | 梯度攔截 | 10–15% 吞吐降低 |
| 存取控制 + 稽核 | 內部威脅 | 營運開銷 |
相關主題
Knowledge Check
為什麼以 NCCL 為基礎的梯度通訊是多節點 LLM 訓練的資安疑慮?