###### tags: `security incident` # CVE-2020-9054 漏洞分析 ## TL;DR 由於這個漏洞已經被 Mirai 成功利用,因此就來了解一下,我會分別介紹如何 Extract zyxel firmware 跟 reverse 有問題的 cgi ## Report https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9054 ## Malware 利用 https://thehackernews.com/2020/03/zyxel-mukashi-mirai-iot-botnet.html?fbclid=IwAR2-QybQQGXCr6eFs7m9gshmqSdT4qfOOYw5K_5thLZFo8cFxM8Z-7V0YTI ## POC 發現處 https://kb.cert.org/artifacts/cve-2020-9054.html ## extract firmware 解開firmware有兩種方法 1. 照著[此blog](https://www.pentestpartners.com/security-blog/using-hexdump-analysis-for-firmware-extraction-a-how-to/) 一步一步解開 2. binwalk 無腦暴力拆 下面是我驗證了一下方法1 blog 的正確性 ### 0x00 parse header zyxel 的 firmware 有個特性,前30byte 後是一連串[key][data length][data] 的格式 已我手上的 `NAS520 V5.21(AASZ.3)C0` 解析除來如下 ``` id= 0000 len= 4 data= 1.00 id= 0100 len= 13 data= V5.21(AATB.4) id= 0200 len= 5 data= 51173 id= 0101 len= 4 data= B103 id= 0002 len= 32 data= c6984d9bf878745b9abecc7c50347748 id= 0102 len= 32 data= 49b827a07910c04502e0275364de5128 id= 0202 len= 4 data= A04E id= 0302 len= 4 data= 0000 id= 0402 len= 32 data= 0c5dab12667961fb111f46bdc0e4a496 id= 0010 len= 4 data= 0x10e id= 0110 len= 4 data= 0x7162ed id= 0410 len= 4 data= 0x7162ee id= 0510 len= 4 data= 0x3945e33 id= 00a0 len= 4 data= 0x3945e34 id= 01a0 len= 4 data= 0x394629e id= 02a0 len= 4 data= 0x394629f id= 03a0 len= 4 data= 0x3946654 ``` 可以看到一些明文表示解析的格式是正確的 每個值都是有意義的 ### 0x01 拆內容 利用 id: 0010 ~ 03a0 所提供的 address 可以拆成四段區塊,拆開後用 file 和 md5 驗證,發現id: 0002 和 0402 正確的記錄著我們拆出來的 md5,而另外兩個就先不管,主要的資訊都會放在270.bin 這個 uImage 裡面 ``` 270.bin: u-boot legacy uImage, Linux-3.2.54, Linux/ARM, OS Kernel Image 60055092.bin: POSIX shell script, ASCII text executable 60056223.bin: POSIX shell script, ASCII text executable 7430894.bin: gzip compressed data c6984d9bf878745b9abecc7c50347748 270.bin df27a44b76a9fe182834c785f1713054 60055092.bin 66450075a442dadba541ab9dab57f7fd 60056223.bin 49b827a07910c04502e0275364de5128 7430894.bin ``` **提醒: 上面 header 的address全部都要位移30才是真正的位置(估計是一開始沒有算進前面的header)** 我有寫一個小工具來解前面的部份,如果想要自動化可以參考[此連結](https://github.com/Will03/zyxel_firmware_Extractor) ### 0x02 拆 uzImage 使用 https://gist.github.com/adamvr/1079762 ### 0x03 拆 zImage 接著用 binwalk 就可以挖出 rootfs 了 ## 逆向分析 這部分我稍微列一下步驟 1. 程式流程分析 2. 找到廠商修補處 3. 檢查可疑 Function ### 0x10 程式流程分析 開頭先判斷是否已經有 auth token,如果有就跳到別的地方,但我覺得驗證方式頗怪,之後再來探討 ![](https://i.imgur.com/89I1Mqs.png) 由於網路上已有 POC `username=admin';echo aaa` 利用單引號加分號來關閉,看起來很 sql injection,所以我們就順著看有哪邊可能會照成問題 抓取 username, paaswd, reauth time, lease time ![](https://i.imgur.com/CrTr9Lu.png) 順便檢查了HTML 確定這幾個參數都是會傳進來的 ![](https://i.imgur.com/GMMFjYt.png) 接著檢查有用到 username 的 function,估計漏洞就會在其中一個 function 中 ```c seup_pam_tunnel(&username, &passwd, addr, &rand_num, &reauthtime, &lease_time) uam_find_first_match(&v10, "Web", &username, ip_value) final_response(v12, 1, &rand_num, &username, &passwd, 0) ``` ### 0x12 可疑 function 檢查 #### uam_find_first_match(&v10, "Web", &username, ip_value) 對於username 沒有過多的處理 ![](https://i.imgur.com/03KrCjr.png) #### setup_pam_tunnel(&username, &passwd, addr, &rand_num, &reauthtime, &lease_time) 這個function是用來設定使用者的資訊,並保存起來 而他的 [struct結構]( https://fossies.org/dox/Linux-PAM-1.3.1/structpam__handle.html) 和 [用到的 function call](https://pubs.opengroup.org/onlinepubs/008329799/apdxa.htm) 我直接列網址給大家自行參考。 **找到廠商修補處** 在這個 function 中,新款的多了對 Username 和 password 檢查的機制,在username 的部分禁止 分號和冒號的使用,明顯是為了預防這次的 CVE #### NAS540_V5.21(AATB.4)C0 (修補後) ![](https://i.imgur.com/GiGa8gJ.png) #### NSA325 v2_V4.81(AALS.1)C0 (未修補) ![](https://i.imgur.com/jjoe06K.png) 我想接下來 PAM 的應用就是問題最大的地方,但是 PAM 整體的架構讓我不太好trace所以只好到這裡就罷手了 #### final_response(v12, 1, &rand_num, &username, &passwd, 0) 這部分是最後將 response 整理好回傳的function,看了一遍也沒有特別的 ### 0x12 漏洞成因討論 檢查過一輪後這隻binary沒看到特別處理 username 的地方,最多就用strcmp去比較字串,因此推測是輸入進 pam 後,select 方式有錯誤導致,所以可能要再往後挖才找的到。 ## 附錄 初始 admin 密碼 ![](https://i.imgur.com/I0FiI1K.png) 程式狀態碼 ![](https://i.imgur.com/6Okkaxa.png)