iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Security

Like an Exploition:IoT 韌體漏洞鍊成術系列 第 14 篇

【𝕯𝖆𝖞 𝟏𝟒】

  • 分享至 

  • xImage
  •  

【𝕯𝖆𝖞 𝟏𝟒】

前言

上一篇(Day 13)從 cfg_server 的 opcode dispatch 表發現,cm_processREQ_NC 這個 handler 在未認證的狀態下就可以呼叫,而且它處理的 master_key 欄位沒有做長度檢查。今天把這條路走完:從漏洞成因、到 PoC、到實際洩漏出什麼。

這個 CVE 的價值在於它是教科書級的 length-check missing → OOB read → information disclosure 鏈路,而且不繞過任何防禦、也不需要認證。

[!todo] 待補

  • 補上實際 PoC 腳本完整內容
  • 補上每一步的封包 hex dump
  • 補上實測截圖

0x01 漏洞資訊

欄位 內容
CVE CVE-2022-38105
TALOS ID TALOS-2022-1590
類型 Information Disclosure(OOB read)
CWE CWE-119
CVSS 7.5(AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
影響型號 ASUS RT-AX82U
影響韌體 3.0.0.4.386_49674-ge182230
修補版本 3.0.0.4.386_51925
發現者 Lilith >_<(Cisco Talos)
入口 cfg_server port 7788,opcode 0x3

旁邊還有一個 DoS:CVE-2022-38393 / TALOS-2022-1592,同樣在設定服務的 opcode 上,透過構造封包觸發崩潰。同一批弱點裡面的第三個 CVE-2022-35401 是認證繞過,屬於 Case 03 的範圍。

[!note] 為什麼 CVSS 是 7.5 而不是 9.x
因為這是 read 而不是 write。能讀到設定檔,但寫不進去。要升級成 RCE 通常需要再串一個寫入型弱點。

0x02 成因分析

應該的樣子

cm_processREQ_NC 收到的是一個巢狀 TLV:

struct REQ_NC {
    // ... header ...
    char *master_key;      // 應該剛好 0x20 = 32 bytes(AES-256)
    char *client_nonce;    // 應該剛好 0x20 = 32 bytes
    uint32_t group_id;
};

解析完之後會用它導出 session:

session_key = SHA256(group_id || server_nonce || client_nonce);

之後要對回應做 AES-256 加密/解密。

實際的樣子

問題出在這裡:master_key 的長度沒有被檢查。

// 有問題的邏輯(示意)
int len = subpkt->size;                 // 攻擊者控制
char *mk = malloc(len);                 // 只配置 len bytes
memcpy(mk, subpkt->data, len);

// 之後直接當成 32-byte key 使用
aes_encrypt(resp, resp_len, session_key_derived_from(mk), 0x20);
                                    // ↑ 假設 mk 一定有 32 bytes

攻擊者送出 master_key 長度 = 4 bytes:

malloc(4)  →  heap 上配置一個 4 bytes 的 chunk
aes_encrypt 卻從這個 chunk 開始讀 32 bytes
          →  讀到後面相鄰 chunk 的 metadata 與資料

為什麼會變成資訊洩漏

關鍵在於:越界讀出來的 bytes 會被 fold 進 AES session key。

master_key = [4 bytes 合法輸入] || [28 bytes 越界 heap 資料]
                        ↓
             SHA256(...)
                        ↓
                session_key(攻擊者不知道,但可觀察)
                        ↓
              對回應做 AES-256 加密

這形成了一個 byte-by-byte oracle:

  • 攻擊者送出「前 4 bytes 猜 A,後面 28 bytes 猜 B」
  • 比較 server 回應的密文,就能判斷 A 是不是猜對
  • 因為 OOB 的內容會改變 key,而 AES 的輸出會完全改變
  • 逐 byte 猜測 → 洩漏出那 28 bytes 的 heap 內容

[!todo] 待補

  • 補上 aes_encrypt 的實際簽章與長度參數
  • 補上 decompiled 關鍵程式碼片段
  • 補上 malloc(4) 與後續 read 32 的 ASAN 證據

0x03 攻擊模型

為什麼算 unauthenticated

cm_processREQ_NC 在 opcode dispatch 裡屬於「不需要既有 session」的那一組。攻擊者連 KU(拿 public key)都不需要,直接從 0x3 開始送。

正常流程:KU → 得到 public key → 組出合法的 NC(長度正確)→ 認證成功
攻擊流程:直接送 NC(長度錯誤)→ OOB read → oracle

影響

  • 設定檔內容洩漏:heap 上鄰接的資料可能是其他 session 的 buffer、NVRAM 映射、或 credential
  • 資訊洩漏可作為後續攻擊的 stepping stone:拿到 credential 或 session 相關資料後,可能串到更高階的弱點
  • 需要網路可達 7788,不需要認證

[!todo] 待補

  • 確認 7788 是 WAN 可達還是僅 LAN(Day 13 表格要補)
  • 補上實際洩漏到的資料內容截圖(如果 lab 允許的話)

0x04 環境準備

選項 A:實體設備

項目 內容
設備 ASUS RT-AX82U
韌體 3.0.0.4.386_49674-ge182230
網路 直連 LAN,攻擊機設同網段
韌體來源 需自備 archive

選項 B:EMUX(可重用前幾天的環境)

沿用 Day 07 建立的 EMUX 架構。本 Case 的環境參數集中列在下表,後續 Case 沿用同一組值。

項目 內容
Container emux-tenda-ac15
Network ac15-lab
Guest IP 192.168.100.2
SSH localhost:22222
目標服務 cfg_server(port 7788)
韌體來源 Day 13 從 RT-AX82U_3.0.0.4.386_49674-ge182230.trx 取得
架構 ARM(與前幾天的 MIPS guest 不同)
依賴 vendor NVRAM / libnvram / 設定檔 header CRC
環境成熟度 🟡 部分(見下方待補)
# 進入既有 container
CONTAINER="emux-tenda-ac15"
GUEST="192.168.100.2"
SSH_PORT="22222"

$ docker exec -it "$CONTAINER" bash

[!warning] Container 名稱一致性
EMUX 的 container 命名規則是 emux-<vendor>-<model>,本課程一律使用 emux-tenda-ac15。
若你沿用舊的 runbook 看到 emux-ac15,那個名稱不存在,docker exec 會直接失敗。

這個 Case 比前幾天難在哪裡

cfg_server 是 ARM + 依賴 vendor NVRAM,EMUX 起來的難度比 httpd 高,需要處理:

  • cfg_server 需要 /var/nvram 或 CFM 檔
  • 可能需要 vendor 提供的 libnvram / 加密函式
  • 設定檔的 header CRC 要正確

[!todo] 待補

  • 補上 EMUX 啟動 cfg_server 的實際步驟
  • 記錄卡住的地方(這對 Case 06 的 emulation 內容很有價值)

這個環境能證明什麼

依 Day 18 的三級證據分類,本 Case 的產出可以這樣標示:

結論 級別 理由
REQ_TLV header 結構(type/len/crc 12 bytes) ✅ A 從二進位直接讀出,與環境無關
無認證即可讀取 credential 的程式邏輯存在 ✅ A 純邏輯分支,判定過程不碰硬體
設定檔 CRC 驗證可被繞過 ✅ A 純演算法
port 7788 是 WAN 可達還是僅 LAN ⚠️ B 取決於實際路由與防火牆設定
洩漏 credential 的完整性與可用性 ⚠️ B 取決於 vendor NVRAM 的加密強度
能否從讀取擴大為寫入 ⚠️ B 需確認 TLV 處理是否有長度檢查

結論:本 Case 的存在性可以在模擬環境確立(A 級),但可達性與影響範圍必須在實機確認(B 級)。

工具

# 封包構造
pip install scapy

# 十六進位觀察
xxd / hexdump -C

0x05 PoC 建構

Step 1:組出外層 REQ_TLV

# TODO: 補上完整實作
import struct

def make_tlv(tlv_type: int, payload: bytes, crc: int = 0) -> bytes:
    header = struct.pack('<III', tlv_type, len(payload), crc)
    return header + payload

Step 2:組出 NC 的 subpkts

# 三個 subpkt:master_key / client_nonce / group_id
# TODO: 補上 subpkt 的 TLV 格式定義

Step 3:枚舉 master_key 長度

這一步的關鍵是:不要只試一個長度,要掃一段,看回應有沒有變化。

for length in range(0, 64):
    # 送出不同長度的 master_key,記錄回應密文
    # TODO: 記錄到 table

[!todo] 待補

  • 補上長度掃描結果表格:length → response hex
  • 找出從哪個長度開始回應異常

Step 4:byte-by-byte oracle

已知的合法 bytes:[prefix]
猜測區段:      [ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ]
已知 OOB 區段:  [ 猜測區段之後的 28 bytes,全部可控 ]

比對方式:
  送出 A = [prefix] + [guess_byte] + [all 0x41]
  送出 B = [prefix] + [guess_byte ^ 1] + [all 0x41]
  若 ciphertext(A) != ciphertext(B) → 猜測「有效」

為什麼 A 和 B 一定不同?
  因為猜測區段會被 fold 進 SHA256,導致 key 改變
  而 OOB 區域(0x41)維持不變
  → 差異只能來自 guess_byte 命中了真正的 heap 內容

[!todo] 待補

  • 補上實際的猜測函式
  • 記錄猜了幾個 byte、花費多少時間

0x06 異常觀察

如果 master_key 長度給得非常大(例如 0xFFFF),會從 OOB read 升級成 OOB access 崩潰:

# 監看 service 狀態
watch -n1 "netstat -tuln | grep 7788"

# 看 log
dmesg | tail -n 30

[!todo] 待補

  • 這一段跟 CVE-2022-38393(DoS)可以合併講
  • 補上實際的崩潰現象

0x07 影響評估

面向 評估
遠端可達性 需確認 WAN / LAN;報告標為 AV:N
需要認證 否
複雜度 低
影響 設定內容洩漏,可作為後續攻擊前置
單獨可達 RCE 否(read-only)

0x08 小結

今天走完了一條完整的鏈路:

  1. 用 recon 確認 7788 與 unauth opcode 的存在
  2. 從 reverse 找到 master_key 長度未驗證
  3. 理解 OOB bytes 為何會 fold 進 AES key
  4. 把這個副作用做成 byte-by-byte oracle
  5. 完成資訊洩漏

這裡最值得記住的一句話是:不是你寫的長度欄位沒人檢查,而是你假設某個欄位會是某個長度。

同時也留了一個 Case 06 的伏筆:這個 PoC 在真實硬體上好跑,但 cfg_server 在模擬環境裡要處理 NVRAM、CFM、依賴函式庫——這正是下一個 case 要處理的問題。

To Be Continue

下一篇(Day 15)進入 Case 05:Firmware Update 面向。更新機制是整條韌體裡信任邊界最寬鬆的一條路徑,下一篇會拆解從「檢查更新」到「寫入 flash」的完整 pipeline,並找出可以截斷或污染的地方。

References

[1] https://www.talosintelligence.com/vulnerability_reports/TALOS-2022-1590

[2] https://www.talosintelligence.com/vulnerability_reports/TALOS-2022-1592

[3] https://nvd.nist.gov/vuln/detail/CVE-2022-38105

[4] https://nvd.nist.gov/vuln/detail/CVE-2022-38393


上一篇
【𝕯𝖆𝖞 𝟏𝟑】Custom Network Protocol 與 Parser
下一篇
【𝕯𝖆𝖞 𝟏𝟓】Firmware Update 機制分析與常見漏洞
系列文
Like an Exploition:IoT 韌體漏洞鍊成術 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言