聯通光貓管理員密碼分析,不安全的密碼方案
聯通光貓型號:HG220GS-U
軟件版本:E00L3.03
運營商一直在做光貓防破解,對抗升級還是比較快的,所有的分析結論都和版本綁定的,因為運營商或者路由器的開發商看到后可能立馬就改了。
我自己主要是要改為橋接,這個需求其實打聯通的保修電話讓局端改一下應該就能搞定。不過之前看過一兩個老版本的教程,也照葫蘆畫瓢破解成功了,但我手上的這個版本有點麻煩,現有的教程基本都失效了。有點好奇,這次花點時間仔細看了一下,不過這次被某些人打擊得比較厲害,說果然是IT狗雲雲,只知道和代碼過不去。都雲作者痴,誰解其中味!
這個光貓,先要用普通的user用戶和印在光貓背面的密碼登錄進去,然后改鏈接為http://192.168.1.1/servmngr.html,在這個頁面中把管理員帳號enable,telnet、ftp服務也enable了,注意只針對LAN這一側開放訪問。telnet服務的默認用戶名和密碼都是admin。進入telnet后運行sh就是普通的shell界面。這些是在網上仔細搜能搜到的。
既然telnet、ftp權限都有了,那就把文件拿出來分析好了。最后要分析的是下面三個文件,關鍵函數是cgiAuthAdminPassword(),點到為止,有興趣的可以自己看看。話說Ghidra對MIPS的反編譯還是可以看的。新版的IDA 7.5雖然支持MIPS反編譯,不過我沒有。
/bin/httpd
/lib/public/libcms_util.so
/lib/public/libaes.so
下面是根據光貓MAC地址計算CUAdmin這個用戶的密碼。EPON的貓需要用其base MAC,也就是“設備基本信息”那個頁面中看到的MAC/SN的值,大寫。可以看出這個計算很簡單,就是用零補齊后AES加密。EPON類型的光貓,這個密碼和area code也有關。GPON類型的光貓,則是用其serial number計算的,此處未體現。所以光貓的WEB端口千萬不要針對WAN一側開放,否則被探測出MAC地址的話,有可能隨便被人訪問。LAN側如果是很多人能訪問的光貓,也得小心。本質上光貓的這個管理員密碼設定是不安全的,雖然是一機一碼,然而卻是確定的,重復一次:這個密碼方案是不安全的!
所幸的是,管理員CUAdmin賬戶默認沒開啟,需要用一機一碼的user帳號登錄進去后才能開啟。至於user帳號的密碼,有待分析。
#include <stdio.h> #include <atlstr.h> #include <openssl/aes.h> #pragma comment(lib, "libeay32.lib") static const unsigned char encryptionKey[] = "JmpwfGjcfsjpnfJmpwfGjcfsjpnf0000"; void Encrypt(unsigned char *in, size_t inLen, unsigned char *out, size_t &outLen) { AES_KEY aesContext; AES_set_encrypt_key(encryptionKey, 256, &aesContext); outLen = 0; for (size_t k = 0; k < inLen; k += AES_BLOCK_SIZE, outLen += AES_BLOCK_SIZE) { unsigned char padded[AES_BLOCK_SIZE] = {}; memcpy(padded, &in[k], (k + AES_BLOCK_SIZE) < inLen ? AES_BLOCK_SIZE : inLen - k); AES_ecb_encrypt(padded, &out[k], &aesContext, AES_ENCRYPT); } } int main(int argc, char** argv) { static unsigned char mac[] = "112233445566"; constexpr size_t insize = sizeof(mac) - 1; constexpr size_t remain = insize % AES_BLOCK_SIZE; constexpr size_t outsize = remain ? insize - remain + AES_BLOCK_SIZE : insize; unsigned char out[outsize] = {}; size_t outlen = 0; Encrypt(mac, sizeof(mac) - 1, out, outlen); CString passwd; for (size_t k = 0; k < outlen; ++k) { CString t; t.Format(L"%02X", out[k]); passwd += t; } _tprintf(_T("password for CUAdmin: %s\n"), (LPCTSTR)passwd); }