漏洞名称:Windows Server服务RPC请求缓冲区溢出漏洞(MS08-067)
此安全更新解决了服务器服务中一个秘密报告的漏洞。
如果用户在受影响的系统上收到特制的 RPC 请求,则该漏洞可能允许远程执行代码。 在 Microsoft Windows 2000、Windows XP 和 Windows Server 2003 系统上,攻击者可能未经身份验证即可利用此漏洞运行任意代码。 此漏洞可能用于进行蠕虫攻击。 防火墙最佳做法和标准的默认防火墙配置有助于保护网络资源免受从企业外部发起的攻击。
默认情况下能建立空连接。
这个漏洞的利用很复杂,这里转一篇文章,大家可以稍微看一下!
==以下是转载内容===细节=============================================================
这个漏洞就不介绍了,已经沸沸扬扬了。
首先milw0rm上那个exp的编译问题,作者在里面放的些小trick很容易fix,主要麻烦的是midl编译idl文件后,在VC6环境下编译可能出现rcpt库的错误。可能是SDK的版本导致的,云舒用最新的SDK(好像是2008?)编译成功了。
其次是触发问题,什么权限都不需要,空连接后就能触发。
ncacn_np:\\\\192.168.152.101[\\pipe\\srvsvc] 直接请求就可以了。
问题还是出在 NetpwPathCanonicalize() 的第二个参数,这个漏洞非常奇特。
首先这个参数的长度不能超过 0x207(unicode)
71BB58F6 81FF 07020000 CMP EDI,207
71BB58FC ^ 0F87 F447FFFF JA NETAPI32.71BAA0F6 // 如果大于了就直接函数返回了
71BB5902 ^ E9 1247FFFF JMP NETAPI32.71BAA019
然后会走到一个wcscat的地方,这里没有问题,因为空间是足够的
71BAA019 8D85 E8FBFFFF LEA EAX,DWORD PTR SS:[EBP-418]
71BAA01F 53 PUSH EBX
71BAA020 50 PUSH EAX
71BAA021 FF15 9810BA71 CALL DWOrD PTR DS:[<&msvcrt.wcscat>] ; msvcrt.wcscat
继续往下会把所有的 "/" 替换为 "\" 这里也无关紧要
然后就走到出问题的函数
71BAA05A 8D85 E8FBFFFF LEA EAX,DWORD PTR SS:[EBP-418]
71BAA060 50 PUSH EAX
71BAA061 E8 AB020000 CALL NETAPI32.71BAA311
跟进去后很复杂,可以参考下这里的伪代码
Here's the code of the vulnerable function on Windows XP SP3 and Vista SP1:
#include
<wchar.h>
// This is the decompiled function sub_5B86A51B in netapi32.dll on XP SP3
// and sub_6EA11D4D on Vista SP1
int
ms08_067(wchar_t* path)
{
wchar_t* p;
wchar_t* q;
wchar_t* previous_slash = NULL;
wchar_t* current_slash = NULL;
wchar_t ch;
#ifdef
VISTA
int len = wcslen(path);
wchar_t* end_of_path = path + len;
#endif
// If the path starts with a server name, skip it
if ((path[0] == L'\\' || path[0] == L'/') &&
(path[1] == L'\\' || path[1] == L'/'))
{
p = path+2;
while (*p != L'\\' && *p != L'/') {
if (*p == L'\0')
return 0;
p++;
}
p++;
// make path point after the server name
path = p;
// make sure the server name is followed by a single slash
if (path[0] == L'\\' || path[0] == L'/')
return 0;
}
if (path[0] == L'\0') // return if the path is empty
return 1;
// Iterate through the path and canonicalize ..\ and .\
p = path;
while (1) {
if (*p == L'\\') {
// we have a slash
if (current_slash == p-1) // don't allow consequtive slashes
return 0;
// store the locations of the current and previous slashes
previous_slash = current_slash;
current_slash = p;
}
else
if (*p == L'.' && (current_slash == p-1 || p == path)) {
// we have \. or ^.
if (p[1] == L'.' && (p[2] == L'\\' || p[2] == L'\0')) {
// we have a \..\, \..$, ^..\ or ^..$ sequence
if (previous_slash == NULL)
return 0;
// example: aaa\bbb\..\ccc
// ^ ^ ^
// | | &p[2]
// | |
// | current_slash
// |
// previous_slash
ch = p[2];
#ifdef
VISTA
if (previous_slash >= end_of_path)
return 0;
wcscpy_s(previous_slash, (end_of_path-previous_slash)/2, p+2);
#else // XP
wcscpy(previous_slash, &p[2]);
#endif
if (ch == L'\0')
return 1;
current_slash = previous_slash;
p = previous_slash;
// find the slash before p
// BUG: if previous_slash points to the beginning of the
// string, we'll go beyond the start of the buffer
//
// example string: \a\..\
q = p-1;
while (*q != L'\\' && q != path)
q--;
if (*p == L'\\')
previous_slash = q;
else
previous_slash = NULL;
}
else
if (p[1] == L'\\') {
// we have \.\ or ^.\
#ifdef
VISTA
if (current_slash != NULL) {
if (current_slash >= end_of_path)
return 0;
wcscpy_s(current_slash, (end_of_path-current_slash)/2, p+2);
goto
end_of_loop;
}
else { // current_slash == NULL
if (p >= end_of_path)
return 0;
wcscpy_s(p, (end_of_path-p)/2, p+2);
goto
end_of_loop;
}
#else // XP
if (current_slash != NULL) {
wcscpy(current_slash, p+2);
goto
end_of_loop;
}
else { // current_slash == NULL
wcscpy(p, p+2);
goto
end_of_loop;
}
#endif
}
else
if (p[1] != L'\0') {
// we have \. or ^. followed by some other char
if (current_slash != NULL) {
p = current_slash;
}
*p = L'\0';
return 1;
}
}
p++;
end_of_loop:
if (*p == L'\0')
return 1;
}
}
// Run this program to simulate the MS08-067 vulnerability
int
main()
{
return ms08_067(L"\\c\\..\\..\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}
