資安雷達 2026 年 9 月 17 日

2026-09-17 — djust 單日爆 12 個安全公告,最高 CVSS 8.8

primary=https://github.com/advisories/GHSA-7prp-2623-8g45 primary=https://github.com/advisories/GHSA-xhhm-f6hp-2qwj primary=https://github.com/advisories/GHSA-c7c5-5j6r-q957

djust 單日爆 12 個安全公告,最高 CVSS 8.8

GitHub Security Advisories · 2026-09-16

未經驗證的 WebSocket client,只要送出一個帶有任意模組路徑的 mount frame,就能讓 djust 伺服器執行該模組的頂層程式碼,完全不需要密碼、session,或任何身分驗證。這是 GHSA-7prp-2623-8g45(CVSS v4 8.8)描述的核心漏洞,而 2026-09-16 這一天,djust 專案一口氣被揭露了 12 個安全公告,橫跨任意模組匯入、授權繞過到多租戶隔離失效等多種弱點類型。djust 是一套用 WebSocket/SSE 連線打造即時互動 view 的 Python 框架,這波集中揭露幾乎把它的認證與授權模型從頭檢視了一遍。

漏洞機制

djust 的 LiveView 架構會把 view 掛載(mount)在一個由 client 提供的模組路徑上,伺服器端呼叫 __import__(module_path, ...) 把該路徑載入記憶體。問題在於這個匯入動作發生在框架確認被解析物件是 LiveView 子類別、以及執行任何逐一 view 的身分驗證之前,也就是說模組的頂層程式碼會先被執行,才輪到權限檢查。攻擊者不需要登入,只要建立一個 WebSocket 連線並送出 mount frame、指定任何伺服器上可被匯入的模組名稱,就能觸發該模組的初始化程式碼,也可能被用來做匯入炸彈型阻斷服務,或透過錯誤字串枚舉伺服器上裝了哪些模組。

照理說專案可以用 LIVEVIEW_ALLOWED_MODULES 這道白名單擋下未授權的模組路徑,但這個設計本身就預設 fail-open:程式只在 if allowed_modules: 這個設定值有值時才做比對,一旦沒設定,白名單形同不存在;就算有設定,比對邏輯也只用寬鬆的 startswith,不是以模組區段邊界做精準比對,容易被巧妙命名的相鄰路徑繞過。CVSS v4 給到 8.8 分,向量顯示攻擊可透過網路發動、不需任何權限與使用者互動,且對機密性與完整性都有明顯衝擊,代表任何連得上 djust WebSocket 端點的人都可能觸發伺服器端程式碼執行。

受影響版本

受影響版本為早於 1.0.7 的所有 djust 版本,官方已在 1.0.7 修復。同一天揭露的另外兩個案例,同樣把問題根源指向認證與授權模型設計,而不是單一程式碼錯字。GHSA-xhhm-f6hp-2qwj(CVSS 9.1)指出 djust 的即時 WebSocket transport 是靠自訂的 check_view_auth 驗證存取權限,而不是走 Django 標準的 View.dispatch() 鏈,導致 LoginRequiredMixinPermissionRequiredMixin 這類保護只在第一次 HTTP GET 請求時生效,WebSocket 連線建立之後就完全繞過,讓匿名或權限不足的使用者能掛載受保護的 view,包含管理端操作。

另一個案例 GHSA-c7c5-5j6r-q957(CVSS 7.1)揭露物件層級的存取控制只在 WebSocket 路徑上生效,直接用 HTTP GET 存取、透過單頁應用程式(SPA)導覽,或是把受限物件嵌入成子 view,都能繞過原本的授權判斷。這兩個案例合在一起說明同一種設計盲點:djust 在 HTTP、WebSocket、SSE 各自實作一套授權檢查,只要有一條路徑被漏掉,整體防護就形同虛設。

修補與緩解

1.0.7 針對任意模組匯入的修法,是加入一個 fail-closed 的解析閘道 djust._view_resolution.is_view_import_allowed,在任何 __import__ 呼叫之前就先擋下請求,只放行「模組已在 sys.modules 中載入」或「以模組區段邊界精準比對 LIVEVIEW_ALLOWED_MODULES」這兩種情況。換句話說,未知模組預設一律拒絕,而不是預設放行,這正是 fail-open 與 fail-closed 的關鍵差異。

對授權繞過的部分,修法是把所有 render 路徑收斂到單一的 enforce_object_permission 檢查點,並讓 check_view_auth 認得 Django 的 AccessMixin 家族,使 HTTP GET、SPA 導覽、WebSocket mount 走同一套授權邏輯。官方也新增了啟動時的系統檢查 S004,用來提早抓出設定錯誤的認證模式,避免同類問題再度出現。

如果暫時無法升級到 1.0.7,最直接的緩解是手動設定 LIVEVIEW_ALLOWED_MODULES,明確列出允許被掛載的模組路徑,不要讓它維持未設定的 fail-open 狀態;同時盡量改用 djust 原生的 login_requiredpermission_requiredcheck_permissions 屬性,而不是依賴只在 HTTP 層生效的 Django mixin。除了以上三個深入說明的公告,同一批揭露還包含 CSRF、多租戶隔離失效、client 端 mass-assignment 等共 12 個公告,建議把升級到 1.0.7 當成單一動作處理,不必逐一評估每個公告的風險後再決定是否修補。

GHSA IDCVSS說明
GHSA-7prp-2623-8g458.8(v4)未驗證 WebSocket client 可透過 mount frame 觸發任意可匯入模組的程式碼執行
GHSA-xhhm-f6hp-2qwj9.1WebSocket/SSE mount 路徑繞過 Django 標準授權鏈,匿名使用者可掛載受保護 view
GHSA-c7c5-5j6r-q9577.1物件層級存取控制只在 WebSocket 生效,HTTP GET/SPA 導覽/嵌入子 view 可繞過

另外還有 9 個公告涵蓋更多面向:

  • GHSA-v9rj-xjfv-xj9r — WebSocket/runtime 重建請求時遺漏 Host
  • GHSA-pvg3-6q9j-mj3x — Django model 序列化缺少敏感欄位封鎖清單
  • GHSA-c67v-vqrp-m5wj — 未簽章的 client 端狀態快照可提權
  • GHSA-f795-p5jw-j6g2 — SSE session 未綁定已驗證使用者
  • GHSA-4mf4-73j6-mvrw — javascript: URL 觸發的儲存型/反射型 XSS
  • GHSA-pg97-jvmf-qfvc — Server-Sent-Events 傳輸上的 CSRF
  • GHSA-3492-cvg7-9mr2 — 多租戶隔離在 WebSocket/SSE 路徑失效
  • GHSA-cc7c-9jff-58wj — client 端可任意 mass-assignment view 屬性
  • GHSA-8g2f-g3gq-5rjv — 可觀測性端點暴露在網路上

原始來源:GHSA-7prp-2623-8g45GHSA-xhhm-f6hp-2qwjGHSA-c7c5-5j6r-q957


End of article
0
Would love your thoughts, please comment.x
()
x