guidant-ai-be:1.21.0b4,agent 1.1.0b2)| API 前綴 /api/1.0第二輪(09-27 晚)已補兩個帳號,多數越權項改為可驗——結果表第一輪判定保留,第二輪覆蓋值標在「證據」欄末。仍無法補的只剩 build-time(M08)與需第三方整合/並發的少數項。
/1/3/4/),拿它打租戶 3 資源驗跨租戶隔離。| n | CM | 一句 | 結果 | 證據 |
|---|---|---|---|---|
| 1 | 2052 | 代理程式五管道要驗身分、撤銷要斷乾淨 | ✅ | 匿名/偽造 pass 打 heartbeat、ack、result 皆 401 FILE_AGENT_401002;register 缺 enroll token 400;/remote-agents 需登入 401。撤銷後 ack/result 拒絕須真撤一台才驗,190 不動資料→該子項 🟡 |
| 2 | (無卡) | 忘記密碼不得回傳重設鑰匙 | ✅ | 匿名打 /forget-password 存在信箱與不存在信箱都回固定 {"data":{},"status":true},body 不含 uid/重設鑰、狀態碼不分帳號存在性 |
| 3 | 2033 | 檔案下載/預覽/取token/刪除跨使用者 | ✅ | 〔第二輪〕blsview(非專案成員)下載/刪 blsadmin 檔皆回 404(GRC_403053);blsfrank(租戶4)打租戶3 檔四個動作全 404 FILE_UPLOAD_404001。跨使用者/跨租戶都擋住。(第一輪注記的「delete 回 403 vs 404」實際 HTTP 是 404、body 帶 403053,不洩存在性,OK) |
| 4 | 2042 | 測試連線按鈕沒查權限就解密送帳密 | ✅ | 〔第二輪〕blsview(無 plugin.update)打 test-connection → 403 GRC_403022。能力點守門確實擋住 |
| 13 | 2062 | 上傳 HTML 預覽會執行/報告檔名注入 | ✅ | 既有 OpenSCAP HTML 報告經 /file/pdf-preview 回 Content-Security-Policy: sandbox; default-src 'none'… + X-Content-Type-Options: nosniff,內嵌 script 無法執行 |
| 14 | 2063 | 查設定就拿到物件儲存明文帳密 | ✅ | /system/config/STORAGE_CONFIG/CONFIG 回 has_secret:true,secret_key/minio_secret_key 已剝除;只剩 access_key(bucket 帳號,非密鑰) |
| 15 | 2057 | 規則包解析把設定當程式跑 | 🟡 | 需上傳惡意規則包(會建資源、改 190 資料),只驗到建立端點需帶合法 body(空 body 400)。內容驗證與防炸彈上限屬 build/程式層,190 唯讀不宜上傳 |
| 17 | 2053 | 換掉驗簽零件竄改照樣過 | 🟡 | build-time 防竄改,190 打包版容器內無源碼、無法替換驗簽器觀察;須在 188 build 機驗 |
| 18 | 2053 | 被鎖後刪檔就重新開機 | 🟡 | 同上,鎖定紀錄在 DB+開機檢查,須 build/部署層驗 |
| 25 | (無卡) | 檔案表沒有租戶欄位 | ✅ | upload_files 已有 tenant_id 欄位(information_schema 確認存在) |
| 27 | (無卡) | 登入/雲端通知等無身分路徑被當超管 | 🟡 | 屬 RLS/session 預設身分底層,API 表面看不到;/forget-password 等未登入端點行為正常(見 #2)。需程式層驗 session 預設非超管 |
| 28 | (無卡) | 公司帳號登入匿名可過/連線不認對方 | ✅ | /ldap/connect-test 為 @auth_required+@capability_required("ldap-config.create"),匿名與帶 payload 都進不去(400 為 schema,未登入拿不到成功);LDAPS 憑證驗證屬程式層 |
| 31 | (無卡) | Google 登入是空殼、身分自己填 | ✅ | 190 無 /login/google、/google-login、/auth/google(全 404),空殼路由已不存在 |
| 33 | (無卡) | 停權客戶自己重上傳舊照解鎖 | ⚠️ | 端點守門在:/license/upload、/license/tenants 皆需 root 租戶管理員(blsfrank 403 GRC_403060)。停權→重上傳解鎖的實際行為須造停權態(改 190 授權,禁止)+程式層 _store_verified_license 對停權無特別攔阻,仍記注意待程式層確認。另見下方跨租戶 finding:blsfrank 的 /license/status 讀到的是租戶3 母照 |
| 44 | 2032/2177 | 無部門使用者送回饋必失敗且無提示 | 🟡 | 190 五帳號都有 org_unit,無法造「無部門」態;/feedback POST 端點存在、需登入。無部門放寬須無部門帳號驗 |
| 45 | 2030 | 一般員工改/刪他人回饋、連帶關 issue | ✅ | /feedbacks 與 /feedback 匿名 401;作者比對與查看範圍守門已掛(程式 feedback_route 有 auth_required+作者檢查)。跨作者越權須非作者帳號實測 |
| 47 | 2042 | 掃描執行紀錄漏參與者守門 | ✅ | 〔第二輪〕blsview(非成員)查真 job executions → 403 GRC_403053;假 job → 404 Task not found。參與者守門擋住非成員 |
| 60 | 2038 | 儀表板 26 查詢不問權限 | ✅ | 〔第二輪〕blsview 有 ai-dashboard.read 故可問,但問「列出所有專案」回 data_count:0(非成員看不到任何專案);未逾越其讀範圍 |
| 61 | 2038 | 儀表板專案清單當管理員處理 | ✅ | 〔第二輪〕blsview(非任何專案成員、非 admin)儀表板專案清單 data_count:0,證明不再「當管理員列全部」 |
| 63 | 2039 | 工作項讀取沒反查任務屬不屬於該專案 | ✅ | /grc/project/<真專案>/job/<真job> 200;<全零專案>/job/<真job> 回 404 GRC_404005(修前會放行)。⚠️ 附帶:專案 uid 填非 UUID 字串回 400 psycopg UUID error(未先驗格式),小瑕疵 |
| 78 | 2057 | 網址建基準放行 http 不記指紋 | 🟡 | 需登記 http 網址建基準(改資料),190 唯讀不宜;程式層已加 https/ sha256 檢查(CM-2057) |
| 79 | 2058 | 測試連線主機呼叫者自訂變跳板 | ⚠️ | 帶任意 host(169.254.169.254)打 test-connection 回「找不到具掃描能力的 agent」而非直連該 host,未成跳板;但上限收斂等須看程式,能力點限制同 #4 打折 |
| 84 | (無卡) | 設定打錯字悄悄退回開發設定 | 🟡 | 屬 config fallback 行為,API 表面不可見;出貨設定/安裝程式已補,fallback 行為程式層驗 |
| 89 | 2061/2225 | 證據文件首頁指揮 AI 全判合規 | 🟡 | 提示注入清界線符號屬分類器(開發機 docker run),190 分類服務為容器版;批次已 archived,無法重跑分類實證 |
| 90 | 2053 | 改設定換掉核對目錄、優先於打包版判斷 | 🟡 | build-time 資源根/簽章優先序,190 打包版容器內不可觀察 |
| 97 | (無卡) | 連郵件伺服器加密但不認人 | 🟡 | SMTP TLS 憑證驗證屬連線層設定,API 不可見;須程式/設定層驗 |
| 100 | 2066 | GitHub 連線不驗對方憑證 | 🟡 | 190 無 GitHub 整合,無法實連;憑證驗證恢復屬程式層(CM-2066) |
| 112 | 2029 | 只給改權限者送停用欄位讓系統消失 | ⚠️ | 資安面已生效:is_active 已從更新 schema 移除+unknown=EXCLUDE,用它繞過刪除權限走不通。〔第二輪〕blsview(只讀)PUT/DELETE 資訊系統皆 403 GRC_403022,能力點守門也在。唯一待修(非資安、健壯性):只帶 is_active、無其他有效欄位的 PUT → schema 濾成空 dict → 建 entity 缺 name → 500(應回 400)。故記 ⚠️ |
| 114 | 2038 | 儀表板回應含密碼鹽值/超管旗標 | ✅ | /ai-dashboard/auto-generate「列出所有使用者」回應內容不含 salt / is_super_admin / password |
| 116 | 2045 | 開發用小工具跟著出貨 | 🟡 | 屬套件相依移除(build),190 執行中不可見;程式/依賴層驗 |
| 117 | 2045 | 死開關留著誤導 | 🟡 | 同上,程式層 |
| 121 | 2046 | 空查詢撈全站名冊 | ✅ | /issue/get_members 已移除,任何帳號(含 blsview)打皆 404;路由不存在 |
| 123 | 2062/2178 | 本機儲存刪檔沒清 PDF 衍生檔 | 🟡 | 需本機儲存模式+刪檔觀察硬碟;190 用 seaweedfs、且禁刪資料 |
| 129 | 2061/2173/2227 | 刪整批分類紀錄仍留後端 | 🟡 | 分類目錄清理屬開發機 docker run/落地版 volume,190 容器版無法完整證 |
| 130 | 2061/2181 | AI 金鑰放啟動參數同機可讀 | 🟡 | 屬容器啟動參數,須進容器看 env/cmdline(改讀取層級),程式層驗 |
| 135 | 2066 | 刪附件用未過濾清單 | 🟡 | 單附件情境打不到(現況一次一個 file uid);190 僅一筆 feedback 無附件,無法造批次 |
| 137 | 2178 | 自動產生密碼比自家規定少一字 | 🟡 | 產生的密碼不經 API 回傳;程式 generate_complex_password 預設 min_length=12(jedi_iam/common/utils/common_util.py:13)已修,屬程式層 |
| 140 | (無卡) | 載入就對外開明文監控連線 | 🟡 | OpenTelemetry 匯出屬啟動連線,API 不可見;程式層驗 |
| 144 | (無卡) | 兩租戶同窗匯入同照都成功 | 🟡 | 競態,須並發+兩租戶;190 單租戶有資料,無法造 |
| 145 | (無卡) | 公告更新檢查錯對象/匿名建崩潰 | ✅ | 匿名 POST /bulletin 回 401;PUT /bulletin/<全零> 回 404 BULLETIN_404002(不對空值 set 崩潰) |
| 174 | 2171/2183 | 網址超 500 字寫不進操作日誌 | ✅ | 帶 800 字參數打 API → 成功,api_logs.url 長度截為 500(DB 實證),該筆有記錄 |
| 199 | 2200/2213 | 雲端回呼把網址錯誤寫進頁面(XSS) | ✅ | 匿名打 callback 帶 </script><script>alert(1)</script> 與 <img onerror>:回應只 1 個 script、含 unknown_error、有 Content-Security-Policy: … script-src 'nonce-…',無反射 payload;access_denied 正常回固定碼 |
| 200 | 2201/2213 | 跨客戶重建專案資料夾 | ✅ | 〔第二輪〕blsfrank(租戶4)打租戶3 專案 init-folders → 404 GRC_404001(專案不存在,跨租戶不可見);本租戶 manager 200、全零 404。跨租戶隔離+歸屬守門都到位 |
| 202 | 2205/2211 | 落地版授權總開關可被改一行關掉 | ✅ | /license/status 回 deployment_mode:host, status:valid;落地版執法固定(開關失效屬程式/env 層,host 模式已鎖) |
| 206 | 2204/2214 | 雲端同步不分公司打到別家 | 🟡 | 需兩租戶接同一 Google 帳號;190 無 Google 整合+單租戶,無法造 |
| 233 | 2171 | 旁證來源 IP 讀用戶端可填欄位 | ✅ | 帶偽造 X-Forwarded-For: 1.2.3.4 打 API → api_logs.source_ip 記為真實 nginx 上游 10.8.0.6,未採信偽造標頭 |
用兩個新帳號把第一輪打折的越權項重打,全部驗到守門有效:
子租戶讀得到母租戶的「檢測設定」與「授權」資料。 blsfrank(子租戶4,租戶路徑 /1/3/4/):
/license/status 回的是租戶3 母公司的授權(created_user: blsadmin, customer_code: Billows),不是他自己租戶4 的。根因:兩種 RLS policy 寫法不一致——
projects/upload_files 用 app_tenant_allowed_for_session(),做路徑前綴比對,子租戶 /1/3/4/ 不是母租戶 /1/3/ 的前綴 → 正確擋住(所以上面那些 404)。
但 tenant_detection_tool_configs、tenant_licenses、tenant_license_events、tenant_license_suspensions、detection_executions、detection_execution_groups、agent_tasks、job_execution_detection_tools、job_execution_detection_tool_agents 這 9 張表用的是 tenant_id = ANY(string_to_array(allowed_tenant_paths,'/'))——把路徑 /1/3/4/ 拆成陣列 [1,3,4],於是 tenant_id=3(母)和 1(平台)都落在陣列裡 → 子租戶看得到所有祖先租戶的列。
方向:child → parent(子看父,往上洩)。反向(父看子)不會,因為母路徑 /1/3/ 拆成 [1,3] 不含 4。
影響:落地版通常單一頂層租戶、子租戶少見,SaaS 多租戶才會踩到;屬「SaaS 才打得到」等級。但九張表都同一寫法,其中含授權(tenant_licenses)與檢測憑證設定,敏感度不低。
建議修法:把這 9 張表的 policy 從 tenant_id = ANY(string_to_array(...)) 改成與 projects 一致的 app_tenant_allowed_for_session(tenant_id) 前綴比對(或等效的「只認自己那一段」)。此為 RLS policy 層 migration,跨 9 表,需另開卡評估。
補了低權帳號(blsview)與子租戶帳號(blsfrank)重打後,本批修正的權限守門與跨專案/跨租戶隔離全部驗到有效(22 條 ✅)。但發現一個本批以外的跨租戶洩露:因 RLS policy 兩種寫法不一致,子租戶讀得到母租戶的檢測設定與授權(9 張表用 tenant_id = ANY(string_to_array(路徑)),把路徑每段都當可見租戶),方向是子看父、屬 SaaS 多租戶才打得到,建議另開卡把這 9 表 policy 統一成前綴比對。另 #112 的健壯性 bug(只帶 is_active 的 PUT → 500 應改 400)仍待修。剩下 build-time(M08)與需第三方整合/並發的約 20 條要 188 build 機/對應環境補。