Guidant AI 資安檢視 · 模組報告
管帳號、密碼、角色權限、客戶與部門層級的那一塊——整個產品的地基。這是全案查得最深的一塊,查到的十七條問題全部已修好,包含最嚴重的那一件(知道對方信箱就能接管任何人的帳號,含原廠管理員)。
客戶用這套系統的第一個動作就是登入。這一塊負責的就是從那一刻起的所有事:確認你是誰(帳號密碼、雙因子驗證碼、公司內部帳號系統串接)、記得你是誰(發一張通行證讓你接下來每個動作都不必重新登入)、決定你能做什麼(角色、權限、你屬於哪一家客戶、哪個部門)。
其他每一塊功能都假設這一塊已經把關過了——它們只問「這個人有沒有權限」,不重新問「這個人是不是真的是他」。
這裡破一個洞,後面所有的權限檢查一起失效。
檢視期間:2026-09-05 ~ 2026-09-10|範圍:290 個檔案,切成七塊,七塊加起來涵蓋這一塊的全部正式程式碼(只排除翻譯檔)|共 7 輪
原始技術報告放在需求中心的 FR-075 站,檔名見下表最後一欄。那裡有每一輪的完整技術細節、檔案清單與逐條推理,供需要深究或稽核抽查時查閱。
| 輪次 | 查什麼 | 檔數 | 覆核投票 | 結果 | 原始報告檔名 |
|---|---|---|---|---|---|
| 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(重跑版) |
第七輪(S7)重跑過一次,原因要說清楚
第一次跑的時候範圍放了 74 個檔案,負責找問題的程序跑到別區去了——九條發現裡有八條是第一輪(S1)早就找過的同一批問題,這一輪真正該看的東西反而沒人看。
處理方式是把範圍收窄到 29 個檔案、並在工作單上明寫「不准讀哪幾個路徑」,整輪重跑。重跑後四個疑點零越界,全部落在該看的範圍內。上表列的是重跑後的結果。
另外,重跑那一輪原本指派兩個獨立的查核程序,實際只有一個回報。這一點沒有補救,如實記錄。
第二輪(S2)零發現,但統籌者不接受這個結論——結果是對的
第二輪查權限守門,工具說沒問題。但統籌者注意到一件事:那一輪範圍內有一支程式,它的程式碼說明文字把「出錯時預設放行」寫成是刻意設計,工具讀到那段說明就接受了,沒有再追下去。
統籌者另外開了一張工單(CM-1559)追這件事,後來確認:那個「出錯時預設放行」的設計缺陷確實存在,只是目前沒辦法真的被利用(另一項改動先把入口堵住了)。它不算在這一頁的條目裡,歸在共用基礎那一塊。
這件事的意義:自動工具會被程式碼裡的說明文字說服。看報告時要記得這個盲點。
這一塊十七條問題全部已修好。
包含全案唯一一件最嚴重等級的(第 1 條)。第 10 條(快取伺服器連線)的程式原本有兩份,現在只剩套件那一份修好的;第 17 條(停權後通行證仍可用)由工單 CM-2056 補上,停權當下既有通行證與自動續期一併失效。
排序按風險,同風險的同一類排在一起。「出事會怎樣」那欄講的是業務影響——誰受影響、損失什麼,不是技術現象。
| # | 問題 | 風險 | 分類 | 出事會怎樣(誰受影響) | 怎麼修 | 狀態 |
|---|---|---|---|---|---|---|
| 1 | 登入頁 → 忘記密碼 → 輸入信箱送出時,系統把重設密碼的憑證直接回傳給按下送出的那個人 | 🔴 最嚴重 | 身分驗證缺失 | 知道某人的信箱,就能直接接管那個人的帳號——包含原廠最高權限管理員。不必知道密碼、不必收到那封信;而拿到原廠管理員身分等於拿到全部客戶的資料 | 改成一律回固定的空白內容,憑證只用來組信件連結 | ✅ 已修(工單 CM-1575) 已核對:那支功能現在成功與失敗都回同一個空白結果 |
| 2 | 登入頁 → 用公司帳號登入(串接公司內部帳號系統)這條路上的三個問題:允許匿名登入、查詢條件可被注入、加密連線不驗證對方身分 | 🟠 高 | 身分驗證缺失 | 客戶用公司帳號登入的那條路可以被繞過——匿名也能過,或用特製的帳號字串騙過查詢;加密連線不驗對方身分則代表中間有人可以冒充帳號伺服器、攔下使用者的帳號密碼 | 改成兩段式驗證(查到人之後要再用他輸入的密碼驗一次)、查詢條件做跳脫、加密連線強制驗憑證 | ✅ 已修(工單 CM-1560,其中加密那項退回重做過一次) 已核對:兩段式驗證、跳脫、憑證驗證三項都在,憑證來源改成設定頁欄位 |
| 3 | 個人設定 → 綁定外部帳號(公司帳號、Google)時,沒有確認操作的是本人 | 🟠 高 | 只驗登入、不檢查歸屬 | 任何已登入的員工,可以把自己的外部帳號綁到別人(含管理員)名下,再用那個外部帳號登入變成對方。等於一條自助升權的路 | 綁定與解綁前先確認是本人,或持有管理帳號的權限 | ✅ 已修(工單 CM-1562) 已核對:每一支綁定與解綁功能前面都先過一道「是不是本人或有管理權限」的檢查,不是本人也沒權限就直接擋下 |
| 4 | 個人資料頁 → 儲存自己的資料時,可以順手把自己的權限拉高 | 🟠 高 | 只驗登入、不檢查歸屬 | 任何一般員工可以把自己改成管理員,或把自己的客戶/部門歸屬清空。個人資料頁人人都能開,這是門檻最低的一條升權路 | 自助頁只收該頁真的會改的欄位,角色與歸屬一律不採信送進來的內容、強制沿用資料庫現況 | ✅ 已修(工單 CM-1576) 已核對:角色、客戶、部門、狀態四項現在都從資料庫重新取出覆蓋,送什麼進來都不算 |
| 5 | 登入頁 → 用 Google 登入,這條路其實是個沒接通的空殼 | 🟠 高 | 身分驗證缺失 | 那條路上「你是誰」是呼叫者自己填的——沒有向 Google 驗證過。真的開放使用就等於誰都能宣稱自己是任何人 | 決策者裁定:關閉入口、不刪程式碼 | ✅ 已修(工單 CM-1561) 已核對:入口已關,程式碼留著並在說明文字寫明「現狀不可啟用」與原因 |
| 6 | 登入頁 → 輸入雙因子驗證碼時,可以無限次嘗試 | 🟠 高 | 身分驗證缺失 | 雙因子驗證等於形同虛設——六位數的碼可以一直猜到中為止。客戶買這個功能是為了「就算密碼外流也還有一道」,這道其實不存在 | 加上每人失敗次數上限,超過就讓當前驗證碼失效 | ✅ 已修(工單 CM-1557) 已核對:失敗五次即鎖、驗證碼作廢,且重發驗證碼有冷卻時間(換瀏覽器、清畫面、直接從入口送都繞不過) |
| 7 | 帳號管理 → 編輯使用者 → 順手改密碼時,不檢查密碼強度 | 🟡 中 | 只驗登入、不檢查歸屬 | 密碼強度規則可以被整條繞過——客戶設定的「必須幾位數、要有大小寫」在這條路上完全不生效,使用者可以把密碼改成一個字 | 這條路徑上補上同一套密碼規則檢查 | ✅ 已修(工單 CM-1577) 已核對:建帳號與改帳號兩條路徑都補上了,程式碼旁並加註「這行不可拿掉」的警語 |
| 8 | 登入頁 → 輸入一個不存在的帳號,錯誤訊息會透露「這個帳號存不存在」 | 🟡 中 | 回應夾帶不該送的欄位 | 外部的人可以用大量嘗試,試出貴公司有哪些人的帳號——拿到名單之後才開始猜密碼,攻擊效率高得多 | 帳號不存在與密碼錯誤統一回同一種錯誤 | ✅ 已修(工單 CM-1563) |
| 9 | 系統設定 → 公司帳號系統 → 測試連線時,換了連線位址仍沿用原本填好的密碼 | 🟡 中 | 密碼外流 | 管理員可以把連線位址改成自己的機器、按下「測試連線」,公司帳號系統的密碼就被送過去了 | 位址一改就強制重新輸入密碼 | ✅ 已修(工單 CM-1564) |
| 10 | 系統連「快取伺服器」(暫存登入狀態、驗證碼的那一台)時,加密連線不確認對方身分 | 🟡 中 | 身分驗證缺失 | 開了加密本該確認「對方真的是那台機器」,不確認的話同一個網路裡的人可以冒充它,攔下經過的登入狀態與驗證碼 | 開了加密就必須確認對方身分、不可退回不驗;並把主專案那份複製品刪掉,統一走同一份。問卷與 AI 助手兩個呼叫點已改接套件那份修好的連線程式,主專案自己的複製品已整支刪除 | ✅ 已修(FR-114.3-1/CM-2043,commit d61d5342d)已核對:主專案那份不驗身分的複製品已刪除,問卷與 AI 助手改用套件那份(開加密就強制確認對方身分),全產品只剩一份 |
| 11 | 登入頁 → 機器人驗證那一關,少了設定金鑰時系統預設直接放行 | 🟡 中 | 身分驗證缺失 | 忘記填一個設定值,防機器人那道就整個消失而且不會有任何提示——自動程式可以無限次嘗試登入 | 改成缺金鑰時直接擋下並報錯 | ✅ 已修(工單 CM-1558) 已核對:缺金鑰時直接拒絕;只有開發模式打開時才退回測試金鑰 |
| 12 | 角色與權限設定 → 開啟角色清單或明細,這幾支查詢功能沒有做權限檢查 | 🟡 中偏高 | 只驗登入、不檢查歸屬 | **任何登入帳號都拿得到整份角色權限對照表與成員名冊(含信箱、電話、職稱)——等於把「誰有哪些權限」整張地圖交出去,是後續針對性攻擊的起手式 | 三支讀取功能各補一道權限檢查,清單不再夾帶成員名單 | ✅ 已修**(工單 CM-1585) 已核對:三支讀取功能都掛上了權限檢查,且追進那道檢查的實作確認它真的會擋(沒有持有該權限就直接拒絕,只有最高權限帳號有例外通道) |
| 13 | 角色與權限設定 → 把某個角色停用之後,系統仍然把它當作有效的在用 | 🟡 中 | 只驗登入、不檢查歸屬 | 把某人的角色停用之後,他的權限其實沒有被收回——管理員以為已經處理了,實際上沒有 | 權限查詢時把有效期、狀態、客戶歸屬一起算進去 | ✅ 已修(工單 CM-1586) |
| 14 | 帳號管理 → 批次匯入使用者(上傳 Excel)時,拿上傳者的帳號名稱當存檔資料夾名 | 🟡 中 | 外部送什麼就收什麼 | 帳號名稱如果含有特殊字元,檔案可能被存到不該存的地方 | 帳號名稱只准英數字、句點、底線,格式不對直接拒絕;存檔時再清一次 | ✅ 已修(工單 CM-1578) 已核對:格式不對的帳號名稱在收件那一關就被擋掉,存檔時再清一次;資料夾仍然用帳號名稱,但已經塞不進特殊字元了 |
| 15 | 部門管理/客戶管理/帳號管理 → 開啟清單,這三支查詢功能沒有權限檢查 | 🟡 中 | 只驗登入、不檢查歸屬 | 任何登入帳號拿得到整棵部門樹與使用者清單(含稽核帳號、路徑與附帶資料),與第 12 條是同一個病灶的不同位置 | 三支讀取功能補上權限檢查;查自己的資料仍然放行 | ✅ 已修(工單 CM-1588) 已核對:三支都掛上了;「查自己」那一支的判斷刻意留在程式裡而非掛在入口上,因為要先知道查的是不是本人才決定要不要檢查權限——這是正確的做法,不是漏掛 |
| 16 | 客戶管理/部門管理 → 只改其中一兩個欄位存檔時,會把「上層是誰」清空 | 🟡 中 | 要先做產品決策 | 這不是資安漏洞,是程式寫錯:改一個欄位會意外打壞層級關係,留下一筆「上層是誰」與「完整路徑」互相矛盾的資料。建立部門時「建立者」欄位也從來沒被填過 | 只有真的有送值才更新那個欄位 | ✅ 已修(工單 CM-1589) 已核對:兩處都包了「有送值才寫」的判斷,建立者欄位也補上了 |
| 17 | 帳號管理 → 把某位員工停權之後,他手上的通行證還能繼續用 | 🟡 中 | 身分驗證缺失 | 管理員把離職或調職的員工停權,那個人如果還開著瀏覽器、或存了登入憑證,照樣能繼續操作到憑證過期;而且憑證快到期時系統還會自動幫他續期——等於停權沒有立刻生效,管理員以為人已經擋掉了,實際上沒有 | 現在認人的時候只看「這張通行證有沒有被撤銷」和「這個帳號還在不在」,沒有看「這個帳號是不是已經被停權」。補上這一眼,停權就拒絕;自動續期那一支同樣要擋——效果是停權當下,他手上的通行證立刻失效。實際做法:在 HTTP 與即時連線共用的身分辨識核心補停權判斷,停權當下既有通行證與自動續期一併失效 | ✅ 已修(工單 CM-2056,套件 commit 3a96260b,隨 jedi-iam 1.4.6 出貨)已核對:身分辨識核心判帳號狀態,停權帳號的舊通行證當下被拒、自動續期也走同一道判斷 |
下面只展開需要你自己判斷、或容易被誤解的幾條。 其餘的修法明確,看上面表格的「怎麼修」那一欄就夠了——沒有展開不代表沒查,也不代表不重要。
這是這一塊唯一一件最嚴重等級的問題,而且它已經修好了。
問題是什麼:正常的忘記密碼流程是——你輸入信箱,系統寄一封信給你,信裡有一條專屬連結,點了才能重設密碼。那條連結裡的憑證,是整個流程唯一的鑰匙,它證明「信真的寄到你手上了」。
但原本的程式,在你按下「送出」的那一刻,就把那把鑰匙直接回傳給呼叫的人了。等於你去銀行說「我忘記密碼」,行員當場把補發的密碼唸給站在櫃檯前的人聽——不管那個人是不是本人。
影響:
| 條件 | 這件事 |
|---|---|
| 要先有帳號嗎 | 不用,忘記密碼本來就是未登入的功能 |
| 要知道什麼 | 只要目標的信箱 |
| 能拿到什麼 | 那個帳號的完整控制權 |
| 有上限嗎 | 沒有,任何帳號都適用,包含原廠最高權限管理員 |
拿到原廠管理員身分之後,客戶資料隔離對他不再有意義——他看得到每一家客戶的東西。
怎麼修好的:那支功能現在無論成功或失敗,一律回一份固定的空白結果,憑證只在伺服器內部用來組信件連結,永遠不經由對外的回應送出。已核對現況程式確實如此。
這兩條放在一起看,因為它們是同一個形狀:新增、修改、刪除每一支都有檢查權限,只有「讀取」那幾支沒有。
結果是,管理員在後台把某人的「查看角色」權限關掉,他在畫面上看不到那個選單了,但繞過畫面直接向系統要,一樣拿得到全部資料。管理員會以為自己已經把權限收掉了。
這個形狀在別的模組也出現過(設備與系統清冊那一塊、意見回饋那一塊)。差別在於:這一塊的兩條是疏漏,已經補上了;別處的那幾條是當初刻意的決定,要先由產品面回答「這個決定還算不算數」。
一句話:這一塊查得最深——七輪、290 個檔案、全部正式程式碼都涵蓋,十七條問題全部已修好,包含全案唯一一件最嚴重等級的(「忘記密碼」把鑰匙直接交給敲門的人)。
兩件部署時要注意的事:
一件不能省略的話
「修好的十七條」指的是這七輪在這個範圍內查到的問題,不等於這一塊已經沒有問題。我們的方法查得到「漏了一道判斷」,但沒有辦法保證每個角落都看過——第七輪就是一個例子:第一次跑偏了,重跑才看到該看的東西(第 17 條就是重跑才查出來的)。
| 統計 | |
|---|---|
| 檢視輪數 | 7 輪、290 個檔案(涵蓋這一塊全部正式程式碼) |
| 通過的發現 | 21 條(18 條資安 + 3 條程式錯誤),併成 17 條問題 |
| 最嚴重 | 1 條(已修好) |
| 已修 | 17 條 |
| 部分修 | 0 條 |
| 未修 | 0 條 |