作者:小黑豬@平安銀河安全實驗室
公眾號:https://mp.weixin.qq.com/s/rT53P9EW4xLFV9JLbnLroQ

1. 設備基礎信息

設備硬件: D-Link 816-A2

固件版本: 1.11

固件下載地址:

http://forums.dlink.com/index.php?topic=74118.0

2. 基礎準備工作

2.1. 焊接UART接口獲取shell

通過拆卸焊接UART接口并測量電壓后可以得到如下圖所示的UART接口線序。

img

通過連接串口轉換器后,可以使用任意串口管理軟件連接轉換器查看信息,通過串口可以看到D-Link路由器啟動時的引導信息 等系統成功引導以后按下回車鍵就就可以拿到root權限的shell了。

img

2.2. 上傳測試工具

D-Link 816-A2路由器的busybox shell經過了裁剪,沒有wgetcurlnetcat等各種方便上傳工具的命令,只能通過tftp命令進行上傳。因此這邊可以考慮通過上傳一個針對路由器CPU架構靜態編譯的busybox后即可使用更多的通用命令了。

\# 在本機上用python運行tftp, 可以使用pip安裝
sudo ptftpd -p 69 en7 -D ./static_tools
sudo ptftpd -r -p 69 en7 -D ./# 上傳靜態編譯的mips工具
tftp -g -r mips/busybox.mipsel 192.168.0.200
tftp -g -r mips/gdbserver.mipsle 192.168.0.200# 賦予工具可執行權限
chmod +x ./*

2.3. 打包系統文件

在上傳了新的busybox后即可使用tar命令對原始的系統文件進行打包。在對打包數據進行回傳后即可對程序進行調試和逆向分析了。

# 打包命令
./busybox-mipsel tar -cvf ./system_backup.tar / --exclude=proc --exclude=run -
-exclude=dev --exclude=mnt --exclude=sys

# 回傳打包的數據
# 在自己本機上運行
nc -l 8080 > system_backup.tar

# 在路由器上執行
./busybox-mipsel nc 192.168.0.200 8080 < system_backup.tar

至此我們已經成功的獲取到路由器的內部文件,可以進一步的堆路由器進行深入分析了。

D-Link的Web管理頁面是由goahead進程提供的,該進程監聽TCP的80端口并提供路由器的管理功能。

3.1 管理頁面權限驗證方法分析

D-Link的登錄頁面如下圖所示。

img

輸入賬號密碼后,將會向goform/formLogin接口發送如下圖所示的數據包進行驗證。從數據包中可以看到關鍵的參數有usernamepassword以及tokenid,其中username使用了base64進行編碼,password則進行了某種加密。

img

有趣的是在成功認證后,服務器并沒有返回session或者Cookie相關的數據,僅僅返回了一個重定向到index頁面的數據包。

img

通過對goahead程序的goform/formLogin接口函數進行分析可以看到在驗證過程中函數首先會從nvram中讀取LoginPassword等參數。

img

隨后調用websGetVar函數從我們發送的請求數據中獲取username,password,tokenid參數的值。

img

之后將解析完成的,賬號密碼信息與nvram中保存的賬號密碼信息進行比對。

img

如下圖所示,當判斷認證成功時將會記錄用戶的IP地址至BSS區的變量load_host中并修改login變量為1,失敗則會將1寫入/etc/RAMConfig/confirmlogin文件中,并重定向用戶到登錄頁面。

img

在更新BSS區的變量load_host后則會檢測lan口和wan口的狀態并返回對應的登錄頁面,隨后將0寫入/etc/RAMConfig/confirmlogin文件中。

img

通過上述的分析,實際上D-Link路由器在認證成功后僅僅記錄了成功登錄的用戶IP地址,隨后將是否需要驗證登錄的Flag文件內容設置為了0。

隨后我們可以看一下goahead程序對于不同的url請求所使用的Handler,根據不同的url路徑goahead進程將使用不同的Handler進行處理。下面可以看到有兩個全局Handler,websSecurityHandlerwebsDefaultHandler。

img

首先我們對默認的全局Handler函數websDefaultHandler進行分析。websDefaultHandler會調用websValidateUrl函數對請求的url地址進行檢測,主要的功能是對轉義符號進行處理并避免'../'路徑穿越的問題。

img

隨后以'\'為分割符,循環遍歷url中的路徑,根據../及正常路徑計算路徑深度,避免出現../越界的情況。若是websValidateUrl合法,則將繼續進行后續處理。

img

用戶訪問管理頁面時D-Link對全局認證狀態的檢測過程就在websSecurityHandler這個全局hanlder中。該函數會首先判斷是否啟用了portal管理,如果未進行portal管理則首先對login變量進行檢測,查看是否存在已登錄過的管理主機。

后續的代碼根據是否存在已認證的管理主機進行了兩段額外的處理,接下來我們首先分析不存在登錄管理主機的情況。

此時如果用戶請求的是asp的頁面,則只允許訪問/dir_login.asp/login_fail.asp頁面,其他asp頁面均會被重定向成/dir_login.asp頁面。

而針對已存在登錄管理主機的情況則會檢測最近兩次請求的間隔是否小于0x258(600)毫秒,如果小于600毫秒也會同樣將請求重定向至/dir_login.asp

img

接下來的代碼是共通的處理邏輯,在上圖中的代碼執行完畢后,會再一次對訪問間隔進行檢測,如果間隔小于0x258(600)毫秒,則會清空load_hostlogin等變量。

img

如果間隔正常的話,則會繼續判斷發送請求的主機IP是否與load_host變量中的IP一致,如果不一致則將請求重定向至/dir_login.asp頁面。接下來還會對是否存在訪問限制進檢測,隨后結束這個Handler,將請求交由后續Handler處理。

img

下圖是將判斷portal管理模式之后的驗證過程進行整理后的流程圖,根據下面的流程圖可以發現。在websSecurityHandler中主要是對ASP頁面的請求進行了權限控制,認證方法也僅僅是檢測了一下當前請求主機的IP地址是否與儲存的管理主機的IP地址一致。而針對非ASP頁面的請求則交由其他后續的Handler進行權限處理。

img

另一個重要的Hander就是websFormHandler,下面將對該Handler的主要判斷部分進行分析,該函數首先檢查了是否存在/etc/RAMConfig/tokenid這個文件。如果文件不存在則創建該文件并寫入隨機數字后讀取,存在的話則讀取其中的數據。

img

隨后調用websGetVar函數獲取goform請求中的tokenid參數,并調用websValueCheck對請求數據進行過濾后與文件中的數據進行比對,檢查是否一致。

img

WebsValueCheck函數會對請求的數值進行過濾。過濾的關鍵字如下圖所示,如果請求的數據中包含如下圖所示的關鍵字則不會繼續執行該請求。

img

當tokenid及其他請求的參數全部合法后則代表驗證通過,此時將會從符號中讀取所請求的form名對應的Handler后跳轉執行,如果請求的form在符號中不存在,則會返回form未定義的報錯。

img

這里就出現一個問題了,對應form的請求D-Link只對tokenid進行了校驗,這也意味著只要知道了tokenid, 無需進行其他驗證即可調用所有支持的form請求。根據最初對登錄過程的分析,tokenid可以通過訪問/dir_login.asp頁面進行獲取,這也導致了我們能夠直接獲取到tokenid,從而越權調用所有D-Link支持的form請求。

3.2 form越權漏洞利用

通過對goahead的main函數進行分析,發現了大量的form定義處理的函數注冊。

img

通過對一些列的函數進行分析后,發現了不少有趣的功能,例如下圖所示的SystemCommand

img

非常簡單粗暴,直接傳參command即可進行命令執行。

img

類似的form有很多,通過對部分form進行分析后發現,除了遠程命令執行外,還存在越權修改賬號密碼、查看系統日志、清空系統日志、重置設備等一系列的危險調用。

4. 固件升級流程分析

D-Link DIR-816的升級頁面如下圖所示。

img

選擇升級包后點擊上傳,將會把文件使用post的方式發送給/cgi-bin/upload.cgi接口。

img

根據之前對goahead的分析,cgi-bin目錄所對應的Handler函數為websCgiHandler該函數最后會通過調用websLaunchCgiProc函數執行對應的cgi-bin文件。

img

websLaunchCgiProc函數中將會fork一個子進程,隨后調用execve來執行cgi-bin文件。

img

通過在fork函數處下斷點。我們可以結合上圖的代碼間接的分析出execve函數的參數。

img

POST請求的頭部和尾部數據如下圖所示。

img

4.1 upload.cgi分析

通過對upload.cgi文件進行分析后發現,該文件會從環境變量中讀取SERVER_SOFTWAREUPLOAD_FILENAME這兩個變量。

img

因此我們可以利用如下代碼直接調用upload.cgi進行測試分析。

SERVER_SOFTWARE=lbp_server UPLOAD_FILENAME=/var/cgiHNYyMd /etc_ro/web/cgi-bin/upload.cgi

命令執行后upload.cgi會將上傳的固件進行解析隨后寫入flash中。

img

接下來繼續對upload.cgi進行分析,查看該程序實際執行了哪些操作。在代碼頭部有一系列的文字處理代碼,用途是從我們發送的POST請求數據中提取文件內容,并保存到/var/image.img文件中。隨后調用/bin/imgdecrypt命令對提取的固件進行解密操作。

img

完成解密操作后,調用/bin/mtd_write命令將解壓后的固件寫入flash中。

img

upload.cgi的主要工作就是上面說明的這些,因此固件升級的核心部分就是/bin/imgdecrypt命令。

4.2 imgdecrypt分析

imgdecrypt比較有趣,他會根據自身文件名來判斷執行鏡像的解密或加密操作。

img

decrypt_firmare函數頭部,首先會將0123456789ABCDEF字符串寫入到棧中。

img

隨后調用sub_40266C函數計算用于解密鏡像的key。

img

通過對在sub_40266C 函數進行分析后,可以發現改函數主要從地址0x403010處開始獲取用于aes解密的key,iv等一系列的數據。隨后調用decryptData函數進行解密。

img

0x403010 地址處的數據如下圖所示,成功利用下列數據解密后的key為C05FBF1936C99429CE2A0781F08D6AD8

后續的代碼會將計算完的key在終端進行打印。

img

打印出的key和aes解密結算的結果與之前計算的一致。

img

隨后程序會調用verify_image對鏡像進行解密操作,相關的參數如下圖所示。

img

verify_image函數首先會判斷鏡像的頭部是否為SHRS。

img

通過對verify_image頭部的代碼進行分析后發現,該函數首先會判斷image頭部的magic是否為SHRS,

隨后從鏡像中的第8~12個字節讀取用于解密數據的長度字段,接著在鏡像文件偏移量0x6dc開始獲取加密的數據內容進行sha512校驗,將結果與鏡像偏移量0x9C處的sha512值進行比對。

鏡像頭部的部分結構如下圖所示。

img

0x9C處存儲了加密數據的sha512校驗值。

img

0x5C處存儲了原始數據的sha512校驗值。

img

當加密數據的SHA512值校驗通過后,將會對加密數據調用decryptData進行解密,decryptData函數的參數如下圖所示。

img

decryptData函數調用的參數值如下。

img

解密完成后,將會計算解密后數據的SHA512值并從鏡像0x5C處讀取SHA512值并進行校驗。

img

在完成了全部的校驗值計算后會調用verifyMD對解密和加密的數據進行RSA簽名驗證。

img

當簽名全部驗證通過后,將會把解密后的鏡像保存到/var/.firmware.orig文件中。

img

隨后回到upload.cgi中,調用/bin/mtd_write命令將解密后的鏡像文件寫入到flash中。

img

至此固件升級的流程就分析完畢了,由于固件升級包使用了RSA簽名校驗,因此直接偽造固件升級包的難度很大,只能與其他漏洞相結合的方式實現寫入自定義固件的效果。

5. 自定義固件寫入研究

D-Link DIR-816 A2路由器的文件系統是直接加載在內存中的,每次重啟后都會從flash中的kernel image里重新讀取加載。這樣的設計方式可以提升系統的健壯性,在避免異常斷電造成的文件損壞的同時,也使得傳統惡意程序無法駐留在路由器中。本章節主要為了方便后續的研究及對植入駐留型惡意程序的可行性進行探索,對該路由器刷寫自定義固件的方法進行了探索及研究。

5.1 防磚準備工作

為了能夠安全的進行固件寫入測試,首先我們需要對flash中的固件進行備份,可以直接從flash中提取或是利用上一章節的方法從固件升級包中進行解密提取。下面是通過使用dd命令將MTD設備中的Kernel部分導出到web目錄后進行下載備份的方法。

PS: 有Flash編程器的可以免去后續這些麻煩,直接通過編程器從Flash中讀取備份。

# 使用DD命令直接從MTD設備中導出到路由器的web目錄,隨后即可通過網頁http://192.168.0.1/mtd4_Kernel.dump直接下載
cat /proc/mtd 
------------------output------------------
dev:    size   erasesize  name
mtd0: 00400000 00010000 "ALL"
mtd1: 00030000 00010000 "Bootloader"
mtd2: 00010000 00010000 "Config"
mtd3: 00010000 00010000 "Factory"
mtd4: 003b0000 00010000 "Kernel"
------------------------------------------

/home/busybox.mipsel dd if=/dev/mtd4 of=/etc_ro/web/mtd4_Kernel.dump
------------------output------------------
7552+0 records in
7552+0 records out
3866624 bytes (3.7MB) copied, 1.412360 seconds, 2.6MB/s
------------------------------------------

備份完固件后若測試中出現系統異常,只要uboot部分沒有被破壞,即可使用路由器uboot引導界面的第二個菜單功能,進行固件的刷寫還原。通過配置tftp服務器及文件名稱后即可通過tftp進行固件的還原。

img

5.2 linux kernel image分析

由于我們的目的是修改路由器內核中打包的文件,實現篡改數據或植入惡意程序的目的,因此首先要對封裝的Linux kernel image進行分析。

首先使用binwalk對備份的kernel image進行分析可以發現這是一個uimage封裝并使用lzma壓縮的linux kernel image文件。

img

下面的代碼用于手動從uimage封裝的文件中提取lzma壓縮的kernel image文件。

根據uimage中image size字段的大小3772774字節。
dd if=mtd4_Kernel.dump of=kernel_image.lzma bs=1 skip=64 count=3772774

此處遇到了一個坑,一定不能使用新版本的lzma去壓縮,必須要使用特定版本的lzma工具才能正常解壓和壓縮。通過觀察設備的啟動過程可以發現設備是基于ralink的sdk進行開發的,因此我們也需要編譯對應sdk中的lzma和xz等工具對鏡像文件進行處理,否則再重打包鏡像時會出現如下圖所示的錯誤信息。

img

可以在網上搜索MediaTek_ApSoC_SDK_4320_20150414.tar.bz2這個版本的SDK,經測試該SDK中的工具可以用于成功處理我們的這個鏡像文件。

使用編譯好的lzma工具即可成功的解壓該鏡像文件,使用binwalk對解壓后的文件進行分析可以看到該kernel image中有一個使用xz壓縮的文件。基本上在linux kernel image中使用xz壓縮的大多都是rootfs文件,也就是我們實際在路由器中看到的那些文件。

img

由于linux kernel image本身是一個可執行文件,使用binwalk自動解壓會導致提取出不屬于xz部分的數據。根據xz文件格式的特征可以知道xz壓縮文件有其特定的起始標識\xFD\x37\x7A\x58\x5A\x00和結束標識\x59\x5A(xz-file-format)

通過對文件進行分析后,即可得到xz文件在鏡像中的正確起始及結束地址,提取和解壓的命令如下。

dd if=kernel_image of=root_fs.xz bs=1 skip=4763648 count=2384780

# 查看xz文件的內容
~/IoT/tool/bin/xz -l root_fs.xz 
------------------output------------------
Strms  Blocks   Compressed Uncompressed  Ratio  Check   Filename
    1       1  2,328.9 KiB  9,294.0 KiB  0.251  CRC32   root_fs.xz
------------------------------------------

# 解壓xz文件
~/IoT/tool/bin/xz -d root_fs.xz

通過使用file命令可以得知解壓后的xz數據是一個cpio歸檔文件,進一步查看后可以確認這個文件就是我們所需要修改的root_fs文件。

\# 確認解壓后的文件類型
file root_fs
------------------output------------------
root_fs: ASCII cpio archive (SVR4 with no CRC)
\------------------------------------------

\# 使用cpio命令查看歸檔的文件列表
cpio -tv -F root_fs|more
------------------output------------------
drwxrwxr-x 2 541 541 0 Aug 24 19:30 /sys
drwxrwxr-x 2 541 541 0 Aug 24 19:30 /mnt
drwxrwxr-x 2 541 541 0 Aug 24 19:30 /dev
crw--w--w- 1 root 541 240, 0 Aug 24 19:30 /dev/ac0
crw-rw---- 1 root 541 90, 8 Aug 24 19:30 /dev/mtd4
crw--w--w- 1 root 541 217, 0 Aug 24 19:30 /dev/spiS0
crw--w--w- 1 root 541 4, 64 Aug 24 19:30 /dev/ttyS0
brw-rw---- 1 root 541 31, 1 Aug 24 19:30 /dev/mtdblock1
brw-rw---- 1 root 541 31, 6 Aug 24 19:30 /dev/mtdblock6
crw--w--w- 1 root 541 251, 0 Aug 24 19:30 /dev/nvram
crw-rw-rw- 1 root 541 5, 2 Aug 24 19:30 /dev/ptmx
crw-rw-rw- 1 root 541 1, 3 Aug 24 19:30 /dev/null
crw--w--w- 1 root 541 218, 0 Aug 24 19:30 /dev/i2cM0
crw-rw---- 1 root 541 90, 1 Aug 24 19:30 /dev/mtd0ro
crw-rw-rw- 1 root 541 1, 2 Aug 24 19:30 /dev/kmem
crw--w--w- 1 root 541 253, 0 Aug 24 19:30 /dev/rdm0
brw-rw---- 1 root 541 31, 2 Aug 24 19:30 /dev/mtdblock2
\------------------------------------------

下一步就是提取cpio中的文件了,提取命令如下。

創建目錄rootfs
mkdir rootfs
cd rootfs
\# 解壓root_fs歸檔中的文件到rootfs目錄中
cat ../root_fs | cpio -idmvH newc --no-absolute-filenames

\# 成功解壓后即可在目錄中看到歸檔中的文件了。
ls -la
------------------output------------------
total 64
drwxr-xr-x 16 hack hack 4096 1月 16 11:55 .
drwxr-xr-x 4 hack hack 4096 1月 16 11:55 ..
drwxrwxr-x 2 hack hack 4096 1月 16 11:55 bin
drwxrwxr-x 3 hack hack 4096 1月 16 11:55 dev
drwxrwxr-x 2 hack hack 4096 1月 16 11:55 etc
drwxrwxr-x 9 hack hack 4096 1月 16 11:55 etc_ro
drwxrwxr-x 2 hack hack 4096 1月 16 11:55 home
lrwxrwxrwx 1 hack hack 11 1月 16 11:55 init -> bin/busybox
drwxr-xr-x 4 hack hack 4096 1月 16 11:55 lib
drwxrwxr-x 2 hack hack 4096 8月 24 19:30 media
drwxrwxr-x 2 hack hack 4096 8月 24 19:30 mnt
drwxrwxr-x 2 hack hack 4096 8月 24 19:30 proc
drwxrwxr-x 2 hack hack 4096 1月 16 11:55 sbin
\------------------------------------------

此時我們就可以在這個目錄里對原始的文件進行任意的修改,或增加新的文件進去。不過需要注意的是DIR-816 A2路由器所使用的flash容量一共是4M,原始鏡像已經幾乎占滿了所有的空間,因此很難在追加什么新大文件進去。

5.3 重打包linux kernel image

重打包的方法其實就是把解開分析rootfs的方法反著做一遍即可,此處會在進行cpio歸檔時遇到一個小問題,cpio歸檔時無法修改歸檔文件的路徑信息,也就是說我們無法將rootfs目錄下的文件路徑信息修改為/

# 進入rootfs目錄
cd rootfs

# 歸檔rootfs下的所有文件
find . |cpio -H newc -o > ../root_fs.cpio

# 查看歸檔的結果,可以發現文件歸檔的路徑是相對路徑。
cpio -tv -F ../root_fs.cpio|more
------------------output------------------
drwxr-xr-x  16 hack     hack            0 Jan 16 11:55 .
drwxrwxr-x   2 hack     hack            0 Jan 16 11:55 sbin
-rwxr-xr-x   1 hack     hack        29541 Aug 24 19:29 sbin/internet.sh
-rwxr-xr-x   1 hack     hack         3073 Aug 24 19:29 sbin/config-powersave.sh
lrwxrwxrwx   1 hack     hack           14 Jan 16 11:55 sbin/poweroff -> ../bin/busybox
-rwxr-xr-x   1 hack     hack         7356 Aug 24 19:29 sbin/lan.sh
-rwxr-xr-x   1 hack     hack         8981 Aug 24 19:29 sbin/virtual_server_dmz_s
------------------------------------------

此時有個小技巧,可以使用pax命令行工具進行重打包, 利用pax工具的-s參數將路徑名進行替換操作。

使用pax打包rootfs目錄,并對文件路徑使用-s參數替換,替換語法和sed命令的替換方法相同。
pax -w -x sv4cpio -s '/rootfs//' rootfs > root_fs.cpio

\# 查看歸檔的結果,可以發現文件歸檔的路徑已被改寫為/目錄。
cpio -tv -F root_fs.cpio|more
------------------output------------------
drwxrwxr-x 2 hack hack 0 Jan 16 11:55 /sbin
-rwxr-xr-x 1 hack hack 29541 Aug 24 19:29 /sbin/internet.sh
-rwxr-xr-x 1 hack hack 3073 Aug 24 19:29 /sbin/config-powersave.sh
lrwxrwxrwx 1 hack hack 14 Jan 16 11:55 /sbin/poweroff -> ../bin/busybox
-rwxr-xr-x 1 hack hack 7356 Aug 24 19:29 /sbin/lan.sh
-rwxr-xr-x 1 hack hack 8981 Aug 24 19:29 /sbin/virtual_server_dmz_set2.sh
-rwxr-xr-x 1 hack hack 5120 Aug 24 19:29 /sbin/lan_web_filter.sh
-rwxr-xr-x 1 hack hack 1840 Aug 24 19:29 /sbin/portal_manage.sh
-rwxr-xr-x 1 hack hack 1143 Aug 24 19:29 /sbin/automount.sh
-rwxrwxr-x 1 hack hack 238 Aug 24 19:29 /sbin/pt_hotplug
\------------------------------------------

在完成了上述準備工作后即可使用如下python腳本進行重打包。

\# !/usr/bin/env python2
\# coding=utf-8
import sys
import os
original_image_file = open("kernel_image", 'rb')
original_image_data = original_image_file.read()
original_xz_root_fs_start_offset = 0x48b000
original_root_fs_end_offset = 0x6d138c
original_root_fs_size = original_root_fs_end_offset - original_xz_root_fs_start_offset

working_folder = '/home/hack/IoT/D-Link_image'
root_fs_folder_name = 'rootfs'
xz_path = '/home/hack/IoT/tool/bin/xz'
lzma_path = '/home/hack/IoT/tool/bin/lzma'

\# archive rootfs with cpio
cpio_archive_cmd = "cd %s ;pax -w -x sv4cpio -s '/%s//' %s > root_fs.cpio" % (working_folder, root_fs_folder_name, root_fs_folder_name)
print("execute: %s" % cpio_archive_cmd)
os.popen(cpio_archive_cmd)

\# compress rootfs with xz
xz_cmd = "cd %s ;%s --check=crc32 -z -c root_fs.cpio > root_fs.cpio.xz" % (working_folder, xz_path)
print("execute: %s" % xz_cmd)
os.popen(xz_cmd)

\# repack_image
new_image_name = 'kernel_image_hacked.img'
new_image = open(new_image_name, 'wb')
new_xz_root_fs_path = 'root_fs.cpio.xz'
new_xz_root = open(new_xz_root_fs_path, 'rb')
new_xz_root_data = new_xz_root.read()
if len(new_xz_root_data) > original_root_fs_size:
print("new image is too big, exit")
sys.exit()

new_image_data = original_image_data[:original_xz_root_fs_start_offset]
new_image_data += new_xz_root_data + ('\x00' * (original_root_fs_size - len(new_xz_root_data)))
new_image_data += original_image_data[original_root_fs_end_offset:]
new_image.write(new_image_data)

\# compress image with lzma
lzma_cmd = "cd %s ;rm kernel_image_hacked.img.lzma; %s -z kernel_image_hacked.img" % (working_folder, lzma_path)
print("execute: %s" % lzma_cmd)
os.popen(lzma_cmd)

\# make uimage
mkimg_cmd = 'cd %s; mkimage -A MIPS -O Linux -T kernel -C lzma -n "Linux Kernel Image" -a 80000000 -e 8000C2F0 -d kernel_image_hacked.img.lzma kernel_image_hacked.uimg' % (working_folder)
os.popen(mkimg_cmd)

至此一個重新打包過的linux kernel image就制作完成了,我們可以直接使用uboot中刷寫Linux Kernel的功能或是利用漏洞將文件上傳到服務器后結合命令執行漏洞直接調用mtd_write命令進行linux kernel image的覆寫操作。

作為實驗,我改寫了hw_nat.sh文件,添加了從遠端下載shell腳本自動執行的功能。

img

這樣在路由器啟動時就會從tftp服務器中下載shell腳本并執行了。終于不用每次都手工上傳gdbserver和busybox了@_@。

img

6. 總結

這篇文章主要分享的是我研究D-Link DIR-816 A2路由器的過程以及遇到的一些坑,希望這篇文章能夠幫助到那些對IoT安全研究感興趣或是苦于無從下手的同學們。這款路由器的安全問題還是比較多的,針對發現的安全漏洞我們也已于今年1月提交給了D-Link廠商。

PS: 設備中還存在疑似后門的開啟telnet服務的特殊代碼 ^ ^。

img

img


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/1036/