---
title: 登入與權限
eyebrow: Guidant AI 資安檢視 · 模組報告
h1: 登入與權限（jedi-iam）
lede: 管帳號、密碼、角色權限、客戶與部門層級的那一塊——整個產品的地基。**這是全案查得最深、也修得最多的一塊**，連最嚴重的那一件（知道對方信箱就能接管任何人的帳號，含原廠管理員）都已經修好；**但還有一條「把人停權之後，他手上的通行證還能用」沒修，另有一段連線程式修了一份、漏了一份。**
---

## 這塊在產品裡做什麼

客戶用這套系統的第一個動作就是登入。這一塊負責的就是從那一刻起的所有事：**確認你是誰**（帳號密碼、雙因子驗證碼、公司內部帳號系統串接）、**記得你是誰**（發一張通行證讓你接下來每個動作都不必重新登入）、**決定你能做什麼**（角色、權限、你屬於哪一家客戶、哪個部門）。

::: grid2
::: {.card .plain}
#### 它平常在做什麼
1. 登入、忘記密碼、改密碼
2. 發雙因子驗證碼、驗證碼比對
3. 建帳號、改帳號、停權、批次匯入
4. 角色與權限設定、客戶與部門的層級歸屬
:::
::: {.card .warn}
#### 為什麼它是敏感目標
其他每一塊功能都**假設這一塊已經把關過了**——它們只問「這個人有沒有權限」，不重新問「這個人是不是真的是他」。

**這裡破一個洞，後面所有的權限檢查一起失效。**
:::
:::

---

## 檢視軌跡

**檢視期間**：2026-09-05 ～ 2026-09-10｜**範圍**：290 個檔案，切成七塊，七塊加起來涵蓋這一塊的全部正式程式碼（只排除翻譯檔）｜**共 7 輪**

> **原始技術報告**放在需求中心的 [FR-075 站](https://guidantai-feature-doc.jedicotech.com/FR-075-2609-jedi-package-security-audit/)，檔名見下表最後一欄。那裡有每一輪的完整技術細節、檔案清單與逐條推理，供需要深究或稽核抽查時查閱。

| 輪次 | 查什麼 | 檔數 | 覆核投票 | 結果 | 原始報告檔名 |
|---|---|---:|---|---|---|
| **S1** | 登入怎麼驗、串接公司內部帳號系統那條路 | 11 | 全部投完，**八條全部三票一致** | 通過 8 條（5 高、3 中） | `scan-iam-1-auth-and-external-identity` |
| **S2** | 權限怎麼守、有沒有偷偷升權的路 | 8 | 全部投完 | **範圍內零發現**（統籌者仍另開一張工單追查，見下方說明） | `scan-iam-2-authz` |
| **S3** | 雙因子驗證、機器人驗證 | 34 | 全部投完 | 通過 2 條（1 高、1 中） | `scan-iam-3-mfa-turnstile` |
| **S4** | 帳號本體與改密碼 | 43 | 全部投完，**五條全部三票一致** | 通過 5 條（**2 條最嚴重**、1 高、2 中） | `scan-iam-4-user-and-password` |
| **S5** | 角色與權限能力 | 49 | 全部投完 | 通過 2 條（皆中） | `scan-iam-5-role-and-capability` |
| **S6** | 客戶與部門層級 | 47 | 全部投完（8 個疑點投滿 24 票） | 通過 1 條（中）＋3 條不算資安但確實寫錯的程式 | `scan-iam-6-tenant-org-unit` |
| **S7** | 登入狀態、每個請求都會經過的那道共同檢查 | 29 | 全部投完 | 通過 1 條（中）＋人工另外查出 2 條 | `scan-iam-7-login-uiroute-common`（重跑版） |

::: {.callout .warn}
**第七輪（S7）重跑過一次，原因要說清楚**

第一次跑的時候範圍放了 74 個檔案，負責找問題的程序**跑到別區去了**——九條發現裡有八條是第一輪（S1）早就找過的同一批問題，這一輪真正該看的東西反而沒人看。

處理方式是**把範圍收窄到 29 個檔案、並在工作單上明寫「不准讀哪幾個路徑」，整輪重跑**。重跑後四個疑點零越界，全部落在該看的範圍內。**上表列的是重跑後的結果。**

另外，重跑那一輪原本指派兩個獨立的查核程序，實際只有一個回報。**這一點沒有補救，如實記錄。**
:::

::: {.callout .ok}
**第二輪（S2）零發現，但統籌者不接受這個結論——結果是對的**

第二輪查權限守門，工具說沒問題。但統籌者注意到一件事：那一輪範圍內有一支程式，它的程式碼說明文字把「出錯時預設放行」寫成是刻意設計，**工具讀到那段說明就接受了，沒有再追下去。**

統籌者另外開了一張工單（CM-1559）追這件事，後來確認：那個「出錯時預設放行」的設計缺陷確實存在，只是目前沒辦法真的被利用（另一項改動先把入口堵住了）。**它不算在這一頁的條目裡，歸在共用基礎那一塊。**

**這件事的意義**：自動工具會被程式碼裡的說明文字說服。看報告時要記得這個盲點。
:::

---

## 問題一覽

::: {.callout .warn}
**這一塊查得最深、修得也最多，但還沒有全部結案。**

十七條問題裡，**十五條已經修好**（包含全案唯一一件最嚴重等級的），**一條只修了一半**（第 10 條：同一段連線程式有兩份，修了一份、漏了一份），**一條到現在還沒修**（第 17 條：把人停權之後，他手上的通行證還能繼續用）。

第 17 條之所以還沒動，是因為它被查出來的時候，追蹤表已經停止更新，**沒有人替它開工單**——不是沒查到，是查到了沒被接住。
:::

**排序按風險，同風險的同一類排在一起。**「出事會怎樣」那欄講的是**業務影響**——誰受影響、損失什麼，不是技術現象。

| # | 問題 | 風險 | 分類 | 出事會怎樣（誰受影響） | 怎麼修 | 狀態 |
|---|---|---|---|---|---|---|
| **1** | 登入頁 → 忘記密碼 → 輸入信箱送出時，**系統把重設密碼的憑證直接回傳給按下送出的那個人** | 🔴 **最嚴重** | 身分驗證缺失 | **知道某人的信箱，就能直接接管那個人的帳號——包含原廠最高權限管理員**。不必知道密碼、不必收到那封信；而拿到原廠管理員身分等於拿到全部客戶的資料 | 改成一律回固定的空白內容，憑證只用來組信件連結 | ✅ **已修**（工單 CM-1575）<br>已核對：那支功能現在成功與失敗都回同一個空白結果 |
| **2** | 登入頁 → 用公司帳號登入（串接公司內部帳號系統）這條路上的三個問題：允許匿名登入、查詢條件可被注入、加密連線不驗證對方身分 | 🟠 高 | 身分驗證缺失 | **客戶用公司帳號登入的那條路可以被繞過**——匿名也能過，或用特製的帳號字串騙過查詢；加密連線不驗對方身分則代表中間有人可以冒充帳號伺服器、攔下使用者的帳號密碼 | 改成兩段式驗證（查到人之後要再用他輸入的密碼驗一次）、查詢條件做跳脫、加密連線強制驗憑證 | ✅ **已修**（工單 CM-1560，其中加密那項退回重做過一次）<br>已核對：兩段式驗證、跳脫、憑證驗證三項都在，憑證來源改成設定頁欄位 |
| **3** | 個人設定 → 綁定外部帳號（公司帳號、Google）時，**沒有確認操作的是本人** | 🟠 高 | 只驗登入、不檢查歸屬 | **任何已登入的員工，可以把自己的外部帳號綁到別人（含管理員）名下，再用那個外部帳號登入變成對方**。等於一條自助升權的路 | 綁定與解綁前先確認是本人，或持有管理帳號的權限 | ✅ **已修**（工單 CM-1562）<br>已核對：每一支綁定與解綁功能前面都先過一道「是不是本人或有管理權限」的檢查，不是本人也沒權限就直接擋下 |
| **4** | 個人資料頁 → 儲存自己的資料時，**可以順手把自己的權限拉高** | 🟠 高 | 只驗登入、不檢查歸屬 | **任何一般員工可以把自己改成管理員**，或把自己的客戶／部門歸屬清空。個人資料頁人人都能開，這是門檻最低的一條升權路 | 自助頁只收該頁真的會改的欄位，角色與歸屬一律不採信送進來的內容、強制沿用資料庫現況 | ✅ **已修**（工單 CM-1576）<br>已核對：角色、客戶、部門、狀態四項現在都從資料庫重新取出覆蓋，送什麼進來都不算 |
| **5** | 登入頁 → 用 Google 登入，這條路其實是個沒接通的空殼 | 🟠 高 | 身分驗證缺失 | **那條路上「你是誰」是呼叫者自己填的**——沒有向 Google 驗證過。真的開放使用就等於誰都能宣稱自己是任何人 | 決策者裁定：關閉入口、不刪程式碼 | ✅ **已修**（工單 CM-1561）<br>已核對：入口已關，程式碼留著並在說明文字寫明「現狀不可啟用」與原因 |
| **6** | 登入頁 → 輸入雙因子驗證碼時，**可以無限次嘗試** | 🟠 高 | 身分驗證缺失 | **雙因子驗證等於形同虛設**——六位數的碼可以一直猜到中為止。客戶買這個功能是為了「就算密碼外流也還有一道」，這道其實不存在 | 加上每人失敗次數上限，超過就讓當前驗證碼失效 | ✅ **已修**（工單 CM-1557）<br>已核對：失敗五次即鎖、驗證碼作廢，且重發驗證碼有冷卻時間（換瀏覽器、清畫面、直接從入口送都繞不過） |
| **7** | 帳號管理 → 編輯使用者 → 順手改密碼時，**不檢查密碼強度** | 🟡 中 | 只驗登入、不檢查歸屬 | **密碼強度規則可以被整條繞過**——客戶設定的「必須幾位數、要有大小寫」在這條路上完全不生效，使用者可以把密碼改成一個字 | 這條路徑上補上同一套密碼規則檢查 | ✅ **已修**（工單 CM-1577）<br>已核對：建帳號與改帳號兩條路徑都補上了，程式碼旁並加註「這行不可拿掉」的警語 |
| **8** | 登入頁 → 輸入一個不存在的帳號，錯誤訊息會透露「這個帳號存不存在」 | 🟡 中 | 回應夾帶不該送的欄位 | **外部的人可以用大量嘗試，試出貴公司有哪些人的帳號**——拿到名單之後才開始猜密碼，攻擊效率高得多 | 帳號不存在與密碼錯誤統一回同一種錯誤 | ✅ **已修**（工單 CM-1563） |
| **9** | 系統設定 → 公司帳號系統 → 測試連線時，**換了連線位址仍沿用原本填好的密碼** | 🟡 中 | 密碼外流 | **管理員可以把連線位址改成自己的機器、按下「測試連線」，公司帳號系統的密碼就被送過去了** | 位址一改就強制重新輸入密碼 | ✅ **已修**（工單 CM-1564） |
| **10** | 系統連「快取伺服器」（暫存登入狀態、驗證碼的那一台）時，**加密連線不確認對方身分** | 🟡 中 | 身分驗證缺失 | 開了加密本該確認「對方真的是那台機器」，不確認的話**同一個網路裡的人可以冒充它，攔下經過的登入狀態與驗證碼** | 開了加密就必須確認對方身分、不可退回不驗；並把主專案那份複製品刪掉，統一走同一份。問卷與 AI 助手兩個呼叫點已改接套件那份修好的連線程式，主專案自己的複製品已整支刪除 | ✅ **已修**（FR-114.3-1／CM-2043）<br>**同一段連線程式有兩份。套件那份已經修好**（開加密就強制確認對方身分）；**主專案自己那份複製品沒修**，而且問卷與 AI 助手兩個功能正在用那一份。現在加密沒開所以還沒有實際暴露，**但只要開起來，這兩條路就是不確認的**。這是「修一份、漏一份」——**修的人不知道有第二份** |
| **11** | 登入頁 → 機器人驗證那一關，少了設定金鑰時系統預設直接放行 | 🟡 中 | 身分驗證缺失 | **忘記填一個設定值，防機器人那道就整個消失而且不會有任何提示**——自動程式可以無限次嘗試登入 | 改成缺金鑰時直接擋下並報錯 | ✅ **已修**（工單 CM-1558）<br>已核對：缺金鑰時直接拒絕；只有開發模式打開時才退回測試金鑰 |
| **12** | 角色與權限設定 → 開啟角色清單或明細，這幾支查詢功能沒有做權限檢查 | 🟡 中偏高 | 只驗登入、不檢查歸屬 | **任何登入帳號都拿得到整份角色權限對照表與成員名冊（含信箱、電話、職稱）**——等於把「誰有哪些權限」整張地圖交出去，是後續針對性攻擊的起手式 | 三支讀取功能各補一道權限檢查，清單不再夾帶成員名單 | ✅ **已修**（工單 CM-1585）<br>已核對：三支讀取功能都掛上了權限檢查，且**追進那道檢查的實作確認它真的會擋**（沒有持有該權限就直接拒絕，只有最高權限帳號有例外通道） |
| **13** | 角色與權限設定 → 把某個角色停用之後，**系統仍然把它當作有效的在用** | 🟡 中 | 只驗登入、不檢查歸屬 | **把某人的角色停用之後，他的權限其實沒有被收回**——管理員以為已經處理了，實際上沒有 | 權限查詢時把有效期、狀態、客戶歸屬一起算進去 | ✅ **已修**（工單 CM-1586） |
| **14** | 帳號管理 → 批次匯入使用者（上傳 Excel）時，**拿上傳者的帳號名稱當存檔資料夾名** | 🟡 中 | 外部送什麼就收什麼 | 帳號名稱如果含有特殊字元，**檔案可能被存到不該存的地方** | 帳號名稱只准英數字、句點、底線，格式不對直接拒絕；存檔時再清一次 | ✅ **已修**（工單 CM-1578）<br>已核對：格式不對的帳號名稱在收件那一關就被擋掉，存檔時再清一次；**資料夾仍然用帳號名稱，但已經塞不進特殊字元了** |
| **15** | 部門管理／客戶管理／帳號管理 → 開啟清單，這三支查詢功能沒有權限檢查 | 🟡 中 | 只驗登入、不檢查歸屬 | **任何登入帳號拿得到整棵部門樹與使用者清單**（含稽核帳號、路徑與附帶資料），與第 12 條是同一個病灶的不同位置 | 三支讀取功能補上權限檢查；查自己的資料仍然放行 | ✅ **已修**（工單 CM-1588）<br>已核對：三支都掛上了；**「查自己」那一支的判斷刻意留在程式裡而非掛在入口上**，因為要先知道查的是不是本人才決定要不要檢查權限——這是正確的做法，不是漏掛 |
| **16** | 客戶管理／部門管理 → 只改其中一兩個欄位存檔時，**會把「上層是誰」清空** | 🟡 中 | 要先做產品決策 | 這不是資安漏洞，是程式寫錯：**改一個欄位會意外打壞層級關係**，留下一筆「上層是誰」與「完整路徑」互相矛盾的資料。建立部門時「建立者」欄位也從來沒被填過 | 只有真的有送值才更新那個欄位 | ✅ **已修**（工單 CM-1589）<br>已核對：兩處都包了「有送值才寫」的判斷，建立者欄位也補上了 |
| **17** | 帳號管理 → 把某位員工停權之後，**他手上的通行證還能繼續用** | 🟡 中 | 身分驗證缺失 | 管理員把離職或調職的員工停權，**那個人如果還開著瀏覽器、或存了登入憑證，照樣能繼續操作到憑證過期**；而且憑證快到期時系統還會自動幫他續期——**等於停權沒有立刻生效**，管理員以為人已經擋掉了，實際上沒有 | 現在認人的時候只看「這張通行證有沒有被撤銷」和「這個帳號還在不在」，**沒有看「這個帳號是不是已經被停權」**。補上這一眼，停權就拒絕；自動續期那一支同樣要擋——效果是**停權當下，他手上的通行證立刻失效**。實際做法：在 HTTP 與即時連線共用的身分辨識核心補停權判斷，停權當下既有通行證與自動續期一併失效 | ✅ **已修（CM-2056）** |

---

::: {.callout .plain}
**下面只展開需要你自己判斷、或容易被誤解的幾條。** 其餘的修法明確，看上面表格的「怎麼修」那一欄就夠了——**沒有展開不代表沒查，也不代表不重要。**
:::

## 這些問題裡，哪一條最值得記住

### 第 1 條：「忘記密碼」把鑰匙直接交給敲門的人 {#cm1575}

::: {.callout .crit}
**這是這一塊唯一一件最嚴重等級的問題，而且它已經修好了。**
:::

**問題是什麼**：正常的忘記密碼流程是——你輸入信箱，系統寄一封信給你，信裡有一條專屬連結，點了才能重設密碼。**那條連結裡的憑證，是整個流程唯一的鑰匙**，它證明「信真的寄到你手上了」。

但原本的程式，**在你按下「送出」的那一刻，就把那把鑰匙直接回傳給呼叫的人了**。等於你去銀行說「我忘記密碼」，行員當場把補發的密碼唸給站在櫃檯前的人聽——**不管那個人是不是本人。**

**影響**：

| 條件 | 這件事 |
|---|---|
| 要先有帳號嗎 | **不用**，忘記密碼本來就是未登入的功能 |
| 要知道什麼 | **只要目標的信箱** |
| 能拿到什麼 | 那個帳號的完整控制權 |
| 有上限嗎 | **沒有**，任何帳號都適用，包含原廠最高權限管理員 |

拿到原廠管理員身分之後，客戶資料隔離對他不再有意義——**他看得到每一家客戶的東西。**

**怎麼修好的**：那支功能現在無論成功或失敗，一律回一份固定的空白結果，憑證只在伺服器內部用來組信件連結，**永遠不經由對外的回應送出**。已核對現況程式確實如此。

### 第 12、15 條：兩條「權限只在畫面上生效」

這兩條放在一起看，因為它們是同一個形狀：**新增、修改、刪除每一支都有檢查權限，只有「讀取」那幾支沒有。**

結果是，管理員在後台把某人的「查看角色」權限關掉，**他在畫面上看不到那個選單了，但繞過畫面直接向系統要，一樣拿得到全部資料**。管理員會以為自己已經把權限收掉了。

**這個形狀在別的模組也出現過**（設備與系統清冊那一塊、意見回饋那一塊）。差別在於：**這一塊的兩條是疏漏，已經補上了；別處的那幾條是當初刻意的決定，要先由產品面回答「這個決定還算不算數」。**

---

## 這塊的結論

::: {.callout .warn}
**一句話**：這一塊查得最深、修得也最多——七輪、290 個檔案、全部正式程式碼都涵蓋，十七條問題修好了十五條，**包含全案唯一一件最嚴重等級的（「忘記密碼」把鑰匙直接交給敲門的人，已經修好）**。**但還沒有全部結案**：一條「把人停權之後，他手上的通行證還能用」到現在沒修，另一條只修了一份、漏了主專案裡那份一模一樣的複製品。

**建議的順序**：
- **先修第 17 條**——人事異動當下就會踩到，而且客戶很容易發現「停權了人還在用」。
- **接著把第 10 條那份複製品拿掉**，讓問卷與 AI 助手改用已經修好的那一份。以後只剩一份，修一次就全修。

**另外兩件要注意的事**：
- **快取伺服器那條**：環境如果已經開了加密、但憑證沒配好，連線會被直接擋掉。**而且主專案那份複製品還沒修，它連對方身分都不確認。**
- **公司帳號系統那條**：客戶串接自己公司的帳號系統時，**設定頁上要先把憑證貼好，再打開「驗證伺服器憑證」那個開關**——這要寫進操作說明。
:::

::: {.callout .warn}
**一件不能省略的話**

「修好的十五條」指的是**這七輪在這個範圍內查到的問題**，不等於這一塊已經沒有問題。我們的方法查得到「漏了一道判斷」，但**沒有辦法保證每個角落都看過**——第七輪就是一個例子：第一次跑偏了，重跑才看到該看的東西；而重跑查出來的那一條（第 17 條），又因為追蹤表停更而沒有人接手去修。
:::

| 統計 | |
|---|---|
| 檢視輪數 | 7 輪、290 個檔案（涵蓋這一塊全部正式程式碼） |
| 通過的發現 | 21 條（18 條資安 ＋ 3 條程式錯誤），併成 16 張工單；另有第 17 條通過但漏登記，沒有工單 |
| 最嚴重 | 1 條（已修好） |
| **已修** | **15 條** |
| 部分修 | 1 條（第 10 條：套件那份修了，主專案那份複製品沒修） |
| 未修 | 1 條（第 17 條：停權沒有立刻生效） |

---

| 你想知道 | 看哪裡 |
|---|---|
| 我們用什麼方法查、結果有多可信 | [檢視方法與工具](GUIDE-01-method-and-tools.html) |
| 其他模組的檢視結果 | [回總報告首頁](index.html) |
