MoE 路由操弄
Expert3 min readUpdated 2026-03-13
攻擊 Mixture-of-Experts 路由:專家選擇操弄、負載平衡利用、安全專家繞過,以及路由感知對抗輸入。
Mixture-of-Experts(MoE)模型——例如 Mixtral、Switch Transformer 與 DeepSeek-V3——使用稀疏激活來擴展模型容量,而不按比例增加算力。為每個 token 選取專家的路由機制,是一個於密集 transformer 中不存在的新穎攻擊面。
MoE 路由如何運作
在標準 MoE 層中,每個 token 僅由可用專家的子集處理:
# 簡化的 MoE 路由(top-k gating)
class MoERouter(nn.Module):
def __init__(self, d_model, num_experts, top_k=2):
super().__init__()
self.gate = nn.Linear(d_model, num_experts, bias=False)
self.top_k = top_k
def forward(self, x):
# 計算每位專家的路由分數
logits = self.gate(x) # [batch, seq, num_experts]
scores = F.softmax(logits, dim=-1)
# 為每個 token 選取 top-k 專家
top_scores, top_indices = scores.topk(self.top_k, dim=-1)
# 將所選專家權重正規化
top_scores = top_scores / top_scores.sum(dim=-1, keepdim=True)
return top_scores, top_indices關鍵特性
| 特性 | 典型值 | 安全意涵 |
|---|---|---|
| 專家數量 | 每層 8–128 | 專家越多,路由攻擊面越大 |
| Top-k 選取 | 2(多數模型) | 每 token 僅由 2 位專家處理 |
| 負載平衡損失 | 輔助損失項 | 可被利用以強制路由模式 |
| 專家容量 | 固定大小緩衝區 | 溢出會導致 token 被丟棄 |
攻擊向量 1:安全專家繞過
MoE 模型可能發展出專精於安全處理的專家。若攻擊者能打造繞過這些專家的輸入,安全行為將退化。
辨識安全專精專家
對專家激活模式做輪廓
將一組有害提示與一組無害提示通過模型。記錄每一組分別激活了哪些專家。
計算差異激活
辨識「在有害提示(模型拒答時)上被激活的頻率,顯著高於無害提示」的專家。這些即為安全專家的候選。
以消融驗證
暫時將候選安全專家的權重歸零,並測試拒答率。拒答率下降即確認該專家扮演安全角色。
# 針對安全相關輸入,為專家路由做輪廓
def profile_expert_routing(model, tokenizer, prompts, layer_idx=0):
"""記錄每個提示所選取的專家。"""
expert_counts = defaultdict(int)
hooks = []
def capture_routing(module, input, output):
# output 含路由決策
_, indices = output # top_indices: [batch, seq, top_k]
for expert_id in indices.flatten().tolist():
expert_counts[expert_id] += 1
# 在目標 MoE 路由器上註冊 hook
moe_layer = model.layers[layer_idx].moe_router
hooks.append(moe_layer.register_forward_hook(capture_routing))
for prompt in prompts:
inputs = tokenizer(prompt, return_tensors="pt")
with torch.no_grad():
model(**inputs)
for h in hooks:
h.remove()
return expert_counts打造路由對抗輸入
一旦辨識出安全專家,攻擊者可打造「使其隱藏表示把路由帶離安全專家」的輸入:
# 最佳化輸入前綴以避開安全專家的路由
safety_expert_id = 3 # 從輪廓分析取得
prefix_embeds = torch.randn(1, prefix_len, d_model, requires_grad=True)
optimizer = torch.optim.Adam([prefix_embeds], lr=0.01)
for step in range(500):
full_embeds = torch.cat([prefix_embeds, prompt_embeds], dim=1)
router_logits = get_router_logits(model, full_embeds, target_layer)
# 最小化路由至安全專家的機率
safety_score = F.softmax(router_logits, dim=-1)[:, :, safety_expert_id]
loss = safety_score.mean() # 最小化安全專家之激活
loss.backward()
optimizer.step()
optimizer.zero_grad()攻擊向量 2:負載平衡利用
MoE 模型採用輔助性負載平衡損失以防止路由塌縮。此平衡機制可於推論期加以利用。
專家容量溢位
每位專家有固定容量緩衝區。當路由至某專家的 token 多於它能處理之量時,溢出 token 會被丟棄或由後備機制處理:
| 溢出處理 | 行為 | 安全影響 |
|---|---|---|
| Token 丟棄 | 多餘 token 被略過 | 輸入內容可被選擇性丟棄 |
| 後備專家 | 溢出被送往預設專家 | 被迫由可能較弱的專家處理 |
| 容量係數縮放 | 緩衝區動態擴大 | 可能造成 OOM 或延遲尖峰 |
# 以「全部路由至同一專家」的 token 強制溢位
# 可使安全相關關鍵 token 被丟棄
adversarial_tokens = optimize_for_expert(
model, target_expert=0, num_tokens=1000
)
# 將對抗 token 前綴至實際有害提示之前
# 有害提示的 token 可能溢出該安全專家的容量
payload = adversarial_tokens + harmful_prompt攻擊向量 3:專家投毒
在攻擊者能影響模型訓練的情境下(見訓練與微調攻擊),他們可以針對特定專家投毒,同時保留其他專家乾淨:
針對專家的後門
- 辨識目標專家 —— 判定哪位專家處理觸發模式
- 僅投毒該專家的訓練資料 —— 打造會被路由器送至目標專家的樣本
- 結果 —— 後門嵌於單一專家,使其於全域權重分析下更難被偵測
| 偵測方法 | 對專家特定後門的效果 |
|---|---|
| 全域權重統計 | 低——異常被散佈於所有專家 |
| 逐專家權重分析 | 高——異常集中於單一專家 |
| 行為測試 | 中——取決於觸發涵蓋 |
| 路由模式分析 | 高——觸發輸入下路由異常 |
防禦性路由分析
監控路由異常
# 監控路由熵——低熵暗示可能遭操弄
def routing_entropy(router_logits):
"""熵高 = 均勻路由(正常)。
熵低 = 集中路由(可疑)。"""
probs = F.softmax(router_logits, dim=-1)
entropy = -(probs * probs.log()).sum(dim=-1)
return entropy
# 當路由熵低於門檻時標記輸入
for batch in inference_batches:
logits = get_router_logits(model, batch)
entropy = routing_entropy(logits)
if entropy.min() < ENTROPY_THRESHOLD:
flag_suspicious_input(batch, entropy)相關主題
Knowledge Check
為什麼專家容量溢位在 MoE 模型中具安全疑慮?
參考資料
- Switch Transformers: Scaling to Trillion Parameter Models (Fedus et al., 2021) -- MoE 架構
- Mixtral of Experts (Jiang et al., 2024) -- 生產級 MoE 模型
- DeepSeek-V3 Technical Report (2024) -- 進階 MoE 路由