---
title: C23 agent → 客戶受檢主機
eyebrow: Guidant AI 資安檢視總報告 · 連線清單
h1: C23 代理程式 → 客戶受檢主機（SSH :22／WinRM :5985・5986）
lede: 代理程式拿著客戶給的維運帳密，登進客戶自己的伺服器跑檢查的那條線。CINC Auditor／GCB／OpenSCAP 三種主機型工具都走它；Nmap 也走它（登進「執行主機」去跑）。這是整套產品裡**權限最高的一條線**——帳密通常是能 sudo 的。這一頁回答：這條線**怎麼連**、**哪些功能走它**、它帶來**什麼威脅、駭客怎麼打**、我們**要怎麼防、目前做到哪**。
chips:
  - { text: "派掃描時", kind: plain }
  - { text: "客戶維運帳密・可 sudo", kind: warn }
  - { text: "威脅 3 種", kind: accent }
  - { text: "掃描命中 1 條", kind: plain }
---

> **這一頁怎麼來的**：[DFD Level 0](../DFD/dfd-level0.html#c23) 把產品運作時的連線編成 C01～C25；[STRIDE 六頁](../STRIDE/S-spoofing.html)每一條問題都標了發生在哪幾條線。這裡以**連線**為單位整理。命中只有 1 條，另兩種手法是依這條線的特性補的（表內標明）。個別問題修了沒不在這頁講。

## 一、連線圖

```{.mermaid cap="C23 — 代理程式登進客戶主機。帳密由雲端加密存、派工時解密經 C20 下發，agent 寫進記憶體型暫存檔（/dev/shm，0600）給工具讀，用完即刪。紅色：SSH 不驗主機指紋（首次連線誰回應就信誰）、WinRM 預設走明文 5985。"}
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB'}}}%%
flowchart LR
    API["guidant-api<br/>派工時解密帳密"]
    subgraph AGENTBOX["🏢 客戶機房"]
        direction LR
        subgraph AG["evidence-agent"]
            direction TB
            CRED["帳密 → /dev/shm 暫存檔<br/>0600・用完即刪<br/>不進命令列"]
            TOOLS["cinc-auditor（InSpec／GCB）<br/>oscap（OpenSCAP，paramiko）<br/>nmap（登進執行主機跑）"]
            CRED --> TOOLS
        end
        LNX(["🖥 Linux 主機<br/>sshd :22"])
        WIN(["🖥 Windows 主機<br/>WinRM :5985 明文<br/>／:5986 TLS"])
        MITM(["🕵 同網段的人<br/>搶答 SSH／攔 WinRM"])
        TOOLS == "SSH :22 · 密碼或私鑰<br/>不驗主機指紋" ==> LNX
        TOOLS == "WinRM · 帳密<br/>預設 http :5985" ==> WIN
        MITM -. "回應 SSH 握手<br/>或攔明文 WinRM" .-> TOOLS
    end
    API -- "C20 · 心跳回應帶明文帳密" --> AG
    classDef ext fill:#FBFCFC,stroke:#9AA8AA,stroke-dasharray:3 2
    classDef open fill:#FDECEC,stroke:#C0392B
    class LNX,WIN,MITM ext
    class MITM open
```

## 二、這條線怎麼連

| 項目 | 現況 |
|---|---|
| **誰 → 誰** | 客戶機房的 `evidence-agent` → 客戶自己的受檢主機（Linux 或 Windows）。兩端都在客戶內網，我們的雲端**連不到也不碰**這條線 |
| **協定／埠** | **Linux：SSH :22**（CINC Auditor／GCB 由 `cinc-auditor` 的 ssh transport 連；OpenSCAP 與 Nmap 用 paramiko 直連）。**Windows：WinRM**（`cinc-auditor` 的 winrm transport），`winrm_ssl` 開關決定走 **:5985 明文 http** 或 **:5986 TLS**，**預設關、走明文**；開 TLS 時另有 `winrm_self_signed` 可接受自簽憑證 |
| **傳什麼** | 登入後在主機上執行檢查命令（讀設定檔、查服務狀態、跑 oscap／nmap 二進位），把結果拉回 agent。OpenSCAP／Nmap 在遠端家目錄建暫存檔、跑完 SFTP 拉回、`finally` 清掉 |
| **怎麼驗身分** | **代理程式對主機**：客戶填在「檢測工具設定」頁的維運帳密——SSH 走密碼或私鑰（`ssh_password`／`ssh_private_key`），WinRM 走帳密；多數檢查需要 root，所以帳號通常**能 sudo**（Nmap 的 SYN 掃描明文要求 `use_sudo`，對齊受測機的 sudoers 白名單）。**主機對代理程式**：**SSH 不驗主機指紋**——paramiko 設 `AutoAddPolicy`，誰回應握手就信誰（程式註解寫明「無預先分發的 known_hosts 基礎設施，第一版接受首次連線風險」）；WinRM 預設明文沒有身分可驗 |
| **帳密怎麼到 agent 手上** | 雲端加密存 `tenant_detection_tool_configs`，派工時解密、經 [C20](C20-agent-to-frontdoor.html) 心跳回應下發。agent 收到後**不進命令列**（`cinc-auditor --password` 會出現在 `ps`），改寫進 `/dev/shm`（記憶體型檔案系統）的設定檔／私鑰檔，權限 0600，`try/finally` 用完即刪（含例外與取消路徑） |
| **何時存在** | 派主機型掃描時。目標清單由任務參數指定，單次上限 `DETECTION_SCAN_TARGET_MAX_HOSTS`（預設 256） |

依據：agent repo `core/task_executor_connectors/inspec.py`（transport 選擇、`/dev/shm` 設定檔、`winrm_ssl` 預設 False、埠 5985／5986）、`openscap.py:194-214`（`AutoAddPolicy`、`look_for_keys=False`）、`nmap.py`（SSH 型、`use_sudo`、`shlex.quote`）；主專案 `config/config.py:219`；DFD Level 0 §2.6 工具表。

## 三、哪些功能會走這條線

| 群 | 功能 | 對威脅的意義 |
|---|---|---|
| **① 組態合規檢查** | CINC Auditor（InSpec 相容規則包）、GCB（政府組態基準，同引擎換內容）、OpenSCAP（CIS／STIG，Linux 限定） | 登進去**讀**設定、跑檢查命令。權限高但動作是讀；風險在「拿著能 sudo 的帳號登進去的是誰、跑的規則包是誰寫的」（規則包來源見 [C24](C24-agent-to-profile-url.html)） |
| **② 網路探測** | Nmap——agent 登進客戶指定的「執行主機」，在上面跑 `[sudo] nmap` 掃目標網段（這一跳是 C23，掃出去的流量是 [C25](C25-engine-to-targets.html)） | 執行主機要裝 nmap 並放 sudoers 白名單；`targets` 與埠範圍是使用者輸入、直接進命令列（有 `shlex.quote`） |
| **③ 測試連線** | 「測試連線」按鈕經 [C21](C21-api-to-agent-dataplane.html) 叫 agent 對目標主機實連一次 | 目標由按的人填——這就是本頁唯一命中的那條 |

## 四、這條線會帶來什麼威脅、駭客怎麼打

掃描在這條線上抓到 1 條問題（[M03-6](../STRIDE/I-information-disclosure.html#m03-6)）。依這條線的特性再補兩種手法（T2、T3 **無掃描實例**，風險欄標明）。

| # | 風險 | 威脅 | 駭客怎麼打 | 得手什麼 | STRIDE | 實例 |
|---|---|---|---|---|---|---|
| T1 | 🟡 中 | **連到哪由呼叫者填——代理程式替人敲遍內網** | ① 有權按「測試連線」的人；② 目標清單放一整段內網位址；③ agent 逐台用維運帳密去連；④ 從「連得上／被拒／逾時／帳密錯」的差異畫出內網哪些機器活著、開了 SSH 或 WinRM、帳密對不對 | 客戶內網主機存活圖；帳密被送到非預期的主機（若那台是攻擊者的，帳密就外流） | [I 資料外洩](../STRIDE/I-information-disclosure.html) | [M03-6 「測試連線」要連到哪台主機由呼叫者自己指定](../STRIDE/I-information-disclosure.html#m03-6) 🟡 |
| T2 | —（無掃描實例） | **假冒受檢主機，接走帳密**（SSH 不驗指紋／WinRM 明文） | ① 站在 agent 與受檢主機之間（同網段 ARP 欺騙、改 DNS、或控制了目標 IP 曾屬於的機器）；② agent 派掃描時發起 SSH——paramiko `AutoAddPolicy` 不比對主機指紋，攻擊者的 sshd 回應握手就被接受；③ agent 送出密碼（或用私鑰簽挑戰）——密碼直接到手；④ Windows 那頭更簡單：WinRM 預設 :5985 明文，帳密與整段對話在線上就能讀 | 客戶**能 sudo 的維運帳密**；之後用它登進真正的主機 | [S 冒充身分](../STRIDE/S-spoofing.html)、[I 資料外洩](../STRIDE/I-information-disclosure.html) | — |
| T3 | —（無掃描實例） | **受檢主機被入侵後，反過來打代理程式** | ① 某台受檢主機已被攻擊者控制；② agent 用 sudo 帳號登進去跑 oscap／nmap，在遠端家目錄建暫存檔、SFTP 拉回結果；③ 攻擊者替換 oscap／nmap 二進位或動遠端暫存檔，回一份「全部合規」的假報告；④ 或在結果檔裡塞特製內容（超長字串、惡意 XML），讓 agent 解析時卡住或出錯 | 偽造該台主機的稽核結果；讓 agent 的解析卡死 | [T 竄改資料](../STRIDE/T-tampering.html)、[D 讓服務停擺](../STRIDE/D-denial-of-service.html) | — |

**三種手法的共同點**：這條線上流的是**客戶最高權限的鑰匙**，而兩端（agent 主機、受檢主機）都是客戶自己的機器、都可能被入侵。T1 是「鑰匙被送到不該去的門」；T2 是「門是假的，鑰匙被接走」；T3 是「門後面的人是假的，報告被換掉」。產品能管的是 agent 這一端怎麼拿鑰匙、怎麼認門、怎麼信門後面回來的東西——不是客戶內網乾不乾淨。

## 五、我們要怎麼防、目前做到哪

對應三種威脅，防線分六條。D1 直接對應掃描抓到的手法；**標 ◇ 的是依這條線的特性補的標準防線，沒有實例**。「目前」欄寫程式裡實際有的機制；⚠️ 表示只靠慣例或沒有機制。

| # | 防線 | 擋哪種威脅 | 目前做到哪 |
|---|---|---|---|
| D1 | **目標由呼叫者填，就要限量、收斂回應、記下誰按的** | T1 | ✅ 測試連線限 32 台、回應只回成功／失敗、稽核日誌記目標清單與逐台結果（詳 [C21](C21-api-to-agent-dataplane.html) D3）。**裁定不設目標白名單**——哪台算合法目標由客戶管 |
| D2 ◇ | **帳密不落實體磁碟、不進命令列、不進日誌** | T2、T3 的前提（帳密在 agent 主機上的暴露面） | ✅ `/dev/shm` 暫存檔 0600、`try/finally` 刪；✅ `cinc-auditor` 走 `--config` 檔不走 `--password`；✅ log 只記主機與工具；✅ paramiko `look_for_keys=False, allow_agent=False`（不撿本機其他身分）。⚠️ `/dev/shm` 不可用時 fallback 到系統暫存目錄（仍 0600），會落實體磁碟 |
| D3 ◇ | **SSH 要驗主機指紋**：首次連線記下指紋、之後不符就拒（同 SSH 用戶端的 known_hosts）；或由客戶在工具設定頁預填指紋 | T2 | ⚠️ **沒有**。`AutoAddPolicy`＝每次都接受（連「首次信任、之後釘住」都沒做——paramiko 的 AutoAdd 在新 client 物件上每次都是「首次」）。程式註解明寫是第一版的取捨。這是這條線最大的缺口：帳密能 sudo，而對方是誰完全不驗 |
| D4 ◇ | **WinRM 預設走 TLS（:5986）**，明文要客戶明示才開；接受自簽憑證也要明示 | T2 | ⚠️ `winrm_ssl` 預設 `False`、走 :5985 明文。有 TLS 選項（`winrm_ssl`＋`winrm_self_signed`），但預設是不安全的那一邊。Windows 主機預設只開 5985，開 5986 要客戶自己配憑證——所以預設明文有實務理由，但至少畫面要警告 |
| D5 ◇ | **從受檢主機拉回的東西都是外部輸入**：結果檔大小上限、解析逾時、XML 不解析外部實體 | T3 | ✅ Nmap：XML 上限 60MB（`_XML_MAX_BYTES`）、解析顯式 `resolve_entities=False, no_network=True`、XSLT 轉 HTML 走 subprocess 可 kill；✅ 遠端暫存檔 `finally` 清理含失敗路徑。⚠️ **OpenSCAP 沒有對應的結果檔大小上限與解析器設定**（`openscap.py` grep `MAX_BYTES|resolve_entities` 零命中）——兩支同構的 connector 只有一支守了 |
| D6 ◇ | **最小權限帳號**：文件指引客戶給 agent 專用帳號、sudoers 只白名單必要的二進位，而不是給一般維運帳號 | T1～T3 的後果縮小 | ✅ Nmap 的設定指引明寫 sudoers `NOPASSWD: /usr/bin/nmap` 白名單、二進位路徑寫死對齊白名單（`_NMAP_BIN`／`_OSCAP_BIN`）。⚠️ CINC Auditor／GCB 的檢查需要讀各種系統檔，實務上多半要 root 等效權限，沒有「專用帳號最小權限清單」 |

**最該補的一步**：D3。SSH 不驗主機指紋，等於拿著客戶的 root 密碼去敲門、誰應門就給誰。做法不難：agent 本機維護一份 `known_hosts`（首次記、之後比，不符就拒並在掃描結果標紅），或讓客戶在工具設定頁預填主機指紋。這一刀讓 T2 從「同網段就能做」變成「要先攻下那台主機才行」。

## 六、依這些防線，掃描還沒看過的地方

- **整個 agent 的 connector 層不在掃描範圍**：三支 connector 的 SSH／WinRM 連線方式、暫存檔處理、結果解析——六頁 STRIDE 只有 M03-6 一條沾到這條線，且那條其實是雲端那頭的問題。
- **SSH 主機指紋**（D3）：`AutoAddPolicy` 寫在兩支 connector 裡（openscap、nmap），cinc-auditor 的 ssh transport 怎麼處理 host key 沒查（它用 Ruby 的 train-ssh，預設行為另查）。
- **WinRM 明文預設**（D4）：畫面上有沒有提示「未加密」，沒看 FE。
- **OpenSCAP 結果檔的上限與解析器**（D5）：Nmap 有 60MB 上限與安全解析器設定，OpenSCAP 沒有——同構的兩支只守了一支。
- **帳號權限指引**（D6）：客戶實際給的是什麼帳號，產品管不到，但手冊可以寫清楚最小需求。

---

*依據：STRIDE 六頁信任邊界連線標記（CM-2403／2404 驗收後版本）、agent repo `core/task_executor_connectors/inspec.py`／`openscap.py`／`nmap.py`、主專案 `config/config.py`、DFD Level 0 §2.4／§2.6。*
