簡介
報告檢視了一則重大安全公告,內容指出 知識庫平台 MaxKB 允許不受信任的聊天文字驅動 shell 工具。該公告表示 MaxKB 2.10.3-lts 以前的版本均受影響,2.10.5-lts 已修補,且嚴重性評分為 10.0 [1]。我們僅依公告中引用的程式碼追蹤易受攻擊的控制流程,將攻擊建模為一個序列,並討論為何防護措施失敗。
1. 根本原因
任何附加了 tool、MCP tool、skill 或 sub-application 的 assistant,都會透過一個建立在 host-shell 後端上的代理進行路由。當提供這樣的 backend 時,agent framework 會自動暴露
execute
tool,而平台既未移除也未對此進行管制
[1]
。因此,不受信任的聊天內容,或透過 ingest 的文件進行的間接 injection,都可能導致 model 執行 shell commands
[1]
。這個弱點是架構性的:無法區分 instruction 與 data 的 language model,被直接放置在 command interpreter 前面。
2. Code Path Analysis
2.1 Dispatch to the agent
第一個決策點是 chat node。Capability-less chat 永遠不會進入 agent 路徑,但附加任何 tool 或 MCP configuration 會將 request 送到建立 agent 的 generator [1] 。這使得危險的路徑成為使用該產品作為 agent platform 的正常方式。
- if len(mcp_servers_config) > 0 or len(tools) > 0: # Branch condition: true when any MCP server or any tool is attached to the assistant
- # Inside the branch (line 409 of the node) control goes to mcp_response_generator(...) at line 427
2.2 Agent construction
第二段程式碼建立了 agent。shell backend 是觸發自動注入
execute
和 file tools 的原因。
interrupt_on
map 只列出 file operations,因此沒有任何 human approval step 適用於 shell execution
[1]
。公告也指出,僅靠
excluded_tools
無法修復此問題,因為它只是對 model 隱藏 tool,並未從 executor 中移除
[1]
。
- agent = create_deep_agent( # Build the agent object (line 467)
- model=chat_model, # The LLM that will decide which tool to call
- backend=SandboxShellBackend(root_dir=temp_dir, virtual_mode=True), # Shell backend; this auto-adds execute plus filesystem tools (line 469)
- skills=["/skills"], # Skills directory made visible to the agent
- tools=tools, # Only user, MCP and skill tools; no excluded_tools argument is passed
- system_prompt=system_prompt, # Developer instructions, which share a channel with user text
- interrupt_on={"write_file": False, "read_file": False, "edit_file": False}, # Approval map (line 473); there is no execute key, so no human-in-the-loop
- checkpointer=checkpointer, # Persists conversation state between turns
- ) # End of agent construction
- response = agent.astream({"messages": message_list}, config=...) # Untrusted chat messages flow into the agent (line 477)
2.3 The shell backend
第三段程式碼顯示為何 deployment mode 決定了結果。sandbox flag 預設為零,因此在 source deployment 上會跳過 wrapper,command 會直接以 application user 的身份到達 shell [1] 。
- _enable_sandbox = bool(int(CONFIG.get("SANDBOX", 0))) # Read the sandbox flag; the default of 0 means the protection is OFF (line 9)
- _run_user = "sandbox" if _enable_sandbox else getpass.getuser() # Choose the low-privilege user only when the flag is on, else the current user (line 10)
- def execute(self, command, *, timeout=None): # Entry point that the model-facing execute tool calls (line 56)
- ... # Lines omitted in the advisory excerpt
- if _enable_sandbox: # Wrap the command only when the sandbox flag is enabled (line 65)
- command = f'env -i LD_PRELOAD=/opt/maxkb-app/sandbox/lib/sandbox.so ... gosu {_run_user} {command}' # Build one string: clean env, preload library, drop user (line 70)
- return super().execute(command=command, timeout=timeout) # Parent runs it with subprocess.run(command, shell=True)
3. 攻擊順序
下圖模擬了流程。攻擊者不需要 public 或 embedded assistant 的 credentials,反而可以將文字植入稍後由 retrieval 提供的文件中 [1] 。公告報告指出,一個看似 benign、帶有 operations 風格的 request 就足夠了,而一個明顯的 proof filename 則被 model 拒絕,這顯示 alignment 只是減速帶,而非控制機制 [1] 。
4. 為何防護策略會失敗
文件記錄了兩個獨立的失敗。首先,當 flag 關閉時,execution 會直接以 application user 的身份在 host 上發生
[1]
。其次,在官方 image 上,flag 雖在 base image 中設定,但兩個 image 都未定義
USER
directive,因此 process 以 root 身份運行
[1]
。wrapper 僅將第一個 command token 加上 user switch 前綴,而 redirections、pipes 和 substitutions 則由外層的 root shell 評估
[1]
。在報告的測試中,即使內部 identity command 被阻止,redirect 仍產生了一個 root-owned file
[1]
。這就是將 command 引用為單一 argument vector 與將其連接成 shell string 之間的經典差異。
5. Severity Configuration
評分來自以下的 vector。changed-scope component 反映了 exploitation 從 agent 跨越到 host、其他 tenants 和 internal services [1] 。
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H # Protocol 3.1 vector: network reachable (AV:N), low complexity (AC:L), no privileges (PR:N)
- # No user interaction (UI:N), scope changed (S:C), high confidentiality, integrity and availability impact (C:H/I:H/A:H)
6. 相關工作比較
相同的模式也出現在其他地方。一項關於具有 command execution 的 agents 的研究報告指出,argument injection 很常見,而 sandboxing 和 argument separation 能減少影響
[2]
。其避免 shell interpretation 的指導方針與公告中建議傳遞 argument list 而非 string 的建議相符
[1]
[2]
。一份以 MCP 為重點的 risk catalogue 同樣將
subprocess.run(shell=True)
識別為 unsafe sink,並建議拒絕 chaining、redirection 和 command substitution
[3]
。
7. 緩解措施
公告提出了五項措施:預設使用 non-executing backend、要求對
execute
進行 approval、當 sandbox runtime 缺失時 fail closed、以 unprivileged user 的身份將 sandboxed commands 作為 argument list 執行,以及避免僅依賴 tool exclusion
[1]
。這些措施共同在 executor 處強制實施 least privilege,也就是 model 的輸出最終變成 action 的地方。
8. 結論
MaxKB 的缺陷並非單一漏洞,而是多個預設組合造成的:啟用工具的路由、自動加入的 shell 工具、未設限的核准映射、可選的沙箱旗標,以及以字串拼接的命令。由於模型無法被信任去拒絕惡意文字,安全性必須落在執行器端,透過權限降低、明確核准,以及引數向量化執行來保障。