Introduction
這篇筆記是 2024 T5 Camp 的筆試題目以及解題的一些過程跟筆記,也就是 CVE-2023-37144 及 CVE-2022-42168 這兩個漏洞的相關研究及復現,後來也順利錄取並結訓了,但還抽不出時間寫結訓的心得跟專題,有空再來填坑 🫠
因為怕題目掛了,還是備份一下在這:
Original Question
以下題組為對 Tenda 路由器和其一系列 CVE 的研究,包含韌體的解包和逆向、遠程服務的模擬、漏洞的分析和復現等。研究的目標設備為 Tenda AC10 v1.0,韌體版本 V15.03.06.23,可以從官方載點下載。請回答下列問題,並匯整於一份報告中。
- 部份題目需要進行逆向分析並截圖,建議使用 IDA 或 Ghidra。
- 需要實作的題目請額外附上原始檔或腳本,並說明執行的方式和環境 (例如: 需安裝的套件或作業系統等),若不易說明可以直接給 Dockerfile。
- 要分析的漏洞為 CVE-2022-42168 和 CVE-2023-37144,可以參考公開的分析文章。
- 報告最後請附上參考資料連結
1. 解包和逆向分析 (30%)
- 1.1 韌體解包 (5%)
下載該韌體檔 US_AC10V1.0RTL_V15.03.06.23_multi_TD01.bin,並解開內部包含的 squashfs 檔案系統,說明所用的工具和指令。
- 1.2 Web 服務分析 (10%)
找出負責響應 web 登入頁面/管理頁面 (下圖) 的服務和其主執行檔 (httpd),並分析它的啟動流程,包含它和系統中其它服務 (daemon) 的執行順序或依賴關係、交互方式等。
- 1.3 漏洞和攻擊面分析 (15%)
自行查尋 CVE-2022-42168 和 CVE-2023-37144 的相關資訊,並在 httpd 中找出這兩個漏洞。請在逆向工具中截圖、給出漏洞所在的大概位址,並簡略說明這兩個漏洞的原因和觸發方式。例如: 需要送出的 HTTP request 為何? 是否需要多次交互?
此外,說明其他可能的攻擊面,特別是 pre-auth 的部份,即不需先登入即可觸發的攻擊面。例如: 特定的路徑或是 httpd 中某些函式。
2. Web 服務模擬實作 (30%)
使用 qemu-user 或 Qiling 等工具或框架,模擬運行上題中分析的 web 服務主程式 (httpd)。由於缺乏實際的硬體和 kernel,該 web 服務的主程式沒辦法完全直接執行,需要對該 binary 或相關的 shared library 進行修改。建議的方式為:
- 編譯並掛載一個 .so 檔,覆蓋某些 shared library 函式。由於該系統中的 ld-uClibc.so.0 不支援 LD_PRELOAD,因此需要以替換 library 的方式掛載,或重新編譯 ldso (見 bonus-1)。附件中有預先編譯好的 ld-uClibc.so.0 和 Makefile 範例,可以直接修改使用。(==請詳見 ldso_tools.tar.xz 檔案==)
- 直接對主程式或相關 library 進行 binary patch。
- 若使用 Qiling,可以用 address hook 修改其行為。
提示:
- 某些函式可以完全跳過 (直接返回常數),會有部份功能受影響,但頁面顯示和有關前述 CVE 的部份還是可以運作
- Web 服務實際上需要跟其它 daemon 互動,可以直接 patch 掉這部份 (也可以同時運行其它 daemon 的模擬,但難度較高)
- 若使用 root 執行,需注意可能影響到真實系統。可以使用 unshare 或 chroot,或使用 docker 封裝整個環境。也可以修改 bind port (原為 80) 以避免 root 權限。
- 執行的輸出應該會出現
"webs: Listening for HTTP requests at address {ip}:{port}"
字樣,且能以瀏覽器開啟。使用 curl 測試時注意可能有 redirect 和 set-cookie 要處理,使用 python requests 的 Session 會比較方便。 - 由於預設為空白密碼,開啟時會跳過登入頁面直接顯示管理頁面。此為正常行為。
Bonus-1 (+10%)
自行編譯 ld-uClibc.so.0,可以參考其 SoC 之 SDK 中 uclibc 的設定參數。請在報告中寫出方法、指令等。
Bonus-2 (+10%)
使模擬的 web 服務需要登入。瀏覽器首次開啟時會顯示登入頁面,輸入正確密碼後才進入管理頁面。此外,請給出能以正確帳號密碼登入的測試腳本。
提示:
- 較容易實作的方式是 patch/hook httpd 取得帳密設定的程式邏輯,直接回傳固定的 username 和 password hash。
- 正確的 hash 值可以分析 binary 後計算或直接 sniff web request 來取得。
3. 漏洞利用實作 (40%)
以下漏洞利用的實作,評分標準包含腳本的完成度,和能否完整模擬並驗證 PoC 或 exploit 的運作。Demo 部份,附上執行模擬器和腳本的步驟,並對執行的結果截圖即可。此外,如果前一大題沒有完成,可以撰寫只模擬目標漏洞函式的程式來做測試。
3.1 Exploit CVE-2023-37144 (15%)
撰寫一份 CVE-2023-37144 的概念驗證腳本或程式 (PoC):
- 請選擇能「遠端」驗證是否執行成功的 shell command(s),並透過該漏洞來執行。
- 可以假設已知登入帳密或不需登入。
- 如果可行,使用前面完成的 web 服務模擬,來進行 demo,包含前述遠端驗證的部份。
3.2 Exploit CVE-2022-42168 (25%)
撰寫一份 CVE-2022-42168 的利用腳本或程式 (exploit):
- 需要能執行任意 shell command (RCE)。
- 可以假設已知登入帳密或不需登入。
- 嘗試只使用 binary 中的 ROP gadgets,即: 假設 shared library、stack、heap 等會受 ASLR 影響,只使用具固定位址的 gadgets。
- 如果可行,使用前面完成的 web 服務模擬,來進行 demo。
Bonus-3 (+10%)
上述的漏洞都需要先登入才能觸發,因此只是 post-auth,實際上的影響並不大。但只要有能取得密碼或繞過登入驗證的漏洞就可以串接成 pre-auth RCE。已知此韌體版本存在能繞過登入驗證的 CVE 漏洞,請嘗試找到它並將上面的 PoC/exploit 實作為 pre-auth RCE。
如果模擬的 web 服務具有登入功能,請用它來 demo 改良後的 PoC/exploit。
看完了題目,接下來是我的解題過程,雖然完成度不高,但還是幸運錄取了 XD
1. 解包和逆向分析
1.1 韌體解包
首先用 binwalk 就可以簡單解出 filesystem:
1 | $ binwalk US_AC10V1.0RTL_V15.03.06.23_multi_TD01.bin -e |
1.2 Web 服務分析
經過分析後可以得出大致流程(詳細研究過程可見 2.):
- 檢查網路及其他一些設定
- 讀設定檔並進行一些初始化設定(推測是用 cfm 的 daemon 去讀
/webroot/default.cfg
這個檔案,不過靜態逆向看不太出來) - 啟動 socket server
另外也可從 main()
中看出相依的 daemon 為 bin/cfmd
。
再來,我們也可從名稱猜出以下這些都是相依的 daemon:
bin/dhcpcd
bin/dttpd
bin/l2tpd
bin/miniupnpd
bin/p910nd
bin/pppd
bin/pptpd
bin/wscd
bin/xl2tpd
1.3 漏洞和攻擊面分析
CVE-2022-42168
閱讀完 [3.] 的報告後,研究一下 code,可以看到 fromSetIpMacBind()
中,使用者可控的 list
會被 copy 到 mib_buf
中,且沒有做長度檢查;不過由於需要 cookie 驗證,因此是個 post-auth 的漏洞,理論上也只需要一次 request 就可以 成功 RCE,但我們還需要找到繞過驗證的方式才可以善加利用它。
接著確認一下 mib_buf
的長度,僅為 0x80,因此可以看出這是一個 stack overflow 的漏洞。
CVE-2023-37144
閱讀完 [1.] 的報告後,發現這是個超級簡單的 command injection,沒有防禦也沒有限制,所以這個漏洞只需要一個簡單的 GET request,不過由於與前一個一樣是需要驗證的 API,因此一樣暫時為 post-auth 的漏洞。
再來研究一下 code:
再追到 lib/libcommon.so
:
可以看出由於直接將 pcVar1
當成參數傳入 doSystemCmd()
,所以造成 command injection。
2. Web 服務模擬實作
先嘗試把 httpd 跑起來看看:
1 | $ sudo chroot ./ ./qemu-mipsel-static ./bin/httpd |
發現不意外的跑不起來,所以我們先照他的錯誤訊息建立一下資料夾 /proc/sys/kernel
;另外,IoT 一定會做一些 peripherals 的檢查,所以我們需要先 patch 一下 binary 繞過,總之先研究一下 decompile 出來的 code,大概可以猜到這三個部分是需要 patch 的 validation。
下圖是已經 patch 完成的 code,只要簡單的將 asm 換成相反的邏輯就可以,例如:bne
換成 beq
、bgtz
就換成 blez
。
一樣可以對照一下 decompile 的 code:
再跑一次就可以成功執行了!發現又缺少兩個資料夾,所以我們先建立資料夾 /etc
、/proc/sys/net/ipv4
。
1 | $ sudo chroot ./ ./qemu-mipsel-static ./bin/httpd_patched |
完成之後發現他 listen 的 ip 也爛掉了,所以我們繼續閱讀 main()
看能不能找到一些線索。發現這邊很像初始化 IP 的部分,他以 br0IP
這個變數當作名字,並且會指定給 g_lan_ip
,因此我們推測他是會去抓 br0
這張網卡的 IP,所以可以直接新增一張網卡來測試一下。
1 | $ sudo brctl addbr br0 |
加完網卡後再跑一次,發現在前面的 check 卡住了,推測是剛剛把邏輯寫成相反的,結果加網卡後成功讀取,反而卡在前面 check_network()
的地方了,所以把剛剛的 blez
直接 patch 成 b
。
Patch 完就可以看到正常執行,並且也 listen 在正確的 IP 上了 👍
直接用 browser 開看看,發現還是有錯誤。
突然想起剛剛 binwalk 解開的時候有警告說部分的 soft link 自動改到 /dev/null
了,可能就是因為這樣所以才會顯示 page not found。
嘗試建立一個 webroot
並 soft link 到 webroot_ro
看看:
1 | $ ln -s webroot_ro webroot |
成功看到畫面!
另外沿著前面的 main
一路追進去也可以看到 websOpenListen()
這個負責在前面指定的 port 上 listen socket 的 function。
3. 漏洞利用實作
3.1 Exploit CVE-2023-37144
此 POC 不需登入帳密,可見 “Post-auth to Pre-auth” 部分;也可從 script 中看到,request 本身沒有攜帶 cookie 也可執行成功,因此得知此 POC 為 pre-auth RCE。
1 | import sys |
執行結果如下:
1 | $ python3 -m pip install --upgrade pwntools # if you don't install yet |
也可以手動執行:
並到 server 端查看訊息來驗證:
3.2 Exploit CVE-2022-42168
這邊先使用以下 POC 嘗試讓 server crash:
1 | import socket |
但發現 server 端並不會出現 segmentation fault 或 crash 的情況,猜測是 server 為 user-mode 所模擬的,並沒辦法完整複製 router 的行為導致沒辦法成功複現。
1 | python3 so.py |
Bonus-3. Post-auth to Pre-auth
參考 [2.] 的報告,由於 R7WebsSecurityHandler()
這裡的邏輯有漏洞,可以簡單地繞過驗證。從下圖中可以看出,router handler 的檢查是只要在 url 裡發現有 img/main-logo.png
的字串,不管在哪個位置都會略過登入的驗證,因此我們只要構造類似 http://{server}/some/login/required/path?a=img/main-logo.png
的封包,就可以在不影響我們原有的 POC 情況下直接達成 Pre-auth RCE。