---
# System prepended metadata

title: CVE-2020-9054 漏洞分析
tags: [security incident]

---

###### 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)





